commit
ac4113bef1
279 changed files with 13407 additions and 3362 deletions
@ -0,0 +1,259 @@ |
||||
// Generated by the protocol buffer compiler. DO NOT EDIT! |
||||
// source: helloworld.proto |
||||
#pragma warning disable 1591, 0612, 3021 |
||||
#region Designer generated code |
||||
|
||||
using pb = global::Google.Protobuf; |
||||
using pbc = global::Google.Protobuf.Collections; |
||||
using pbr = global::Google.Protobuf.Reflection; |
||||
using scg = global::System.Collections.Generic; |
||||
namespace Helloworld { |
||||
|
||||
/// <summary>Holder for reflection information generated from helloworld.proto</summary> |
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||
public static partial class HelloworldReflection { |
||||
|
||||
#region Descriptor |
||||
/// <summary>File descriptor for helloworld.proto</summary> |
||||
public static pbr::FileDescriptor Descriptor { |
||||
get { return descriptor; } |
||||
} |
||||
private static pbr::FileDescriptor descriptor; |
||||
|
||||
static HelloworldReflection() { |
||||
byte[] descriptorData = global::System.Convert.FromBase64String( |
||||
string.Concat( |
||||
"ChBoZWxsb3dvcmxkLnByb3RvEgpoZWxsb3dvcmxkIhwKDEhlbGxvUmVxdWVz", |
||||
"dBIMCgRuYW1lGAEgASgJIh0KCkhlbGxvUmVwbHkSDwoHbWVzc2FnZRgBIAEo", |
||||
"CTJJCgdHcmVldGVyEj4KCFNheUhlbGxvEhguaGVsbG93b3JsZC5IZWxsb1Jl", |
||||
"cXVlc3QaFi5oZWxsb3dvcmxkLkhlbGxvUmVwbHkiAEI2Chtpby5ncnBjLmV4", |
||||
"YW1wbGVzLmhlbGxvd29ybGRCD0hlbGxvV29ybGRQcm90b1ABogIDSExXYgZw", |
||||
"cm90bzM=")); |
||||
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, |
||||
new pbr::FileDescriptor[] { }, |
||||
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { |
||||
new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloRequest), global::Helloworld.HelloRequest.Parser, new[]{ "Name" }, null, null, null), |
||||
new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloReply), global::Helloworld.HelloReply.Parser, new[]{ "Message" }, null, null, null) |
||||
})); |
||||
} |
||||
#endregion |
||||
|
||||
} |
||||
#region Messages |
||||
/// <summary> |
||||
/// The request message containing the user's name. |
||||
/// </summary> |
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||
public sealed partial class HelloRequest : pb::IMessage<HelloRequest> { |
||||
private static readonly pb::MessageParser<HelloRequest> _parser = new pb::MessageParser<HelloRequest>(() => new HelloRequest()); |
||||
public static pb::MessageParser<HelloRequest> Parser { get { return _parser; } } |
||||
|
||||
public static pbr::MessageDescriptor Descriptor { |
||||
get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[0]; } |
||||
} |
||||
|
||||
pbr::MessageDescriptor pb::IMessage.Descriptor { |
||||
get { return Descriptor; } |
||||
} |
||||
|
||||
public HelloRequest() { |
||||
OnConstruction(); |
||||
} |
||||
|
||||
partial void OnConstruction(); |
||||
|
||||
public HelloRequest(HelloRequest other) : this() { |
||||
name_ = other.name_; |
||||
} |
||||
|
||||
public HelloRequest Clone() { |
||||
return new HelloRequest(this); |
||||
} |
||||
|
||||
/// <summary>Field number for the "name" field.</summary> |
||||
public const int NameFieldNumber = 1; |
||||
private string name_ = ""; |
||||
public string Name { |
||||
get { return name_; } |
||||
set { |
||||
name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); |
||||
} |
||||
} |
||||
|
||||
public override bool Equals(object other) { |
||||
return Equals(other as HelloRequest); |
||||
} |
||||
|
||||
public bool Equals(HelloRequest other) { |
||||
if (ReferenceEquals(other, null)) { |
||||
return false; |
||||
} |
||||
if (ReferenceEquals(other, this)) { |
||||
return true; |
||||
} |
||||
if (Name != other.Name) return false; |
||||
return true; |
||||
} |
||||
|
||||
public override int GetHashCode() { |
||||
int hash = 1; |
||||
if (Name.Length != 0) hash ^= Name.GetHashCode(); |
||||
return hash; |
||||
} |
||||
|
||||
public override string ToString() { |
||||
return pb::JsonFormatter.ToDiagnosticString(this); |
||||
} |
||||
|
||||
public void WriteTo(pb::CodedOutputStream output) { |
||||
if (Name.Length != 0) { |
||||
output.WriteRawTag(10); |
||||
output.WriteString(Name); |
||||
} |
||||
} |
||||
|
||||
public int CalculateSize() { |
||||
int size = 0; |
||||
if (Name.Length != 0) { |
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); |
||||
} |
||||
return size; |
||||
} |
||||
|
||||
public void MergeFrom(HelloRequest other) { |
||||
if (other == null) { |
||||
return; |
||||
} |
||||
if (other.Name.Length != 0) { |
||||
Name = other.Name; |
||||
} |
||||
} |
||||
|
||||
public void MergeFrom(pb::CodedInputStream input) { |
||||
uint tag; |
||||
while ((tag = input.ReadTag()) != 0) { |
||||
switch(tag) { |
||||
default: |
||||
input.SkipLastField(); |
||||
break; |
||||
case 10: { |
||||
Name = input.ReadString(); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
/// <summary> |
||||
/// The response message containing the greetings |
||||
/// </summary> |
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||
public sealed partial class HelloReply : pb::IMessage<HelloReply> { |
||||
private static readonly pb::MessageParser<HelloReply> _parser = new pb::MessageParser<HelloReply>(() => new HelloReply()); |
||||
public static pb::MessageParser<HelloReply> Parser { get { return _parser; } } |
||||
|
||||
public static pbr::MessageDescriptor Descriptor { |
||||
get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[1]; } |
||||
} |
||||
|
||||
pbr::MessageDescriptor pb::IMessage.Descriptor { |
||||
get { return Descriptor; } |
||||
} |
||||
|
||||
public HelloReply() { |
||||
OnConstruction(); |
||||
} |
||||
|
||||
partial void OnConstruction(); |
||||
|
||||
public HelloReply(HelloReply other) : this() { |
||||
message_ = other.message_; |
||||
} |
||||
|
||||
public HelloReply Clone() { |
||||
return new HelloReply(this); |
||||
} |
||||
|
||||
/// <summary>Field number for the "message" field.</summary> |
||||
public const int MessageFieldNumber = 1; |
||||
private string message_ = ""; |
||||
public string Message { |
||||
get { return message_; } |
||||
set { |
||||
message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); |
||||
} |
||||
} |
||||
|
||||
public override bool Equals(object other) { |
||||
return Equals(other as HelloReply); |
||||
} |
||||
|
||||
public bool Equals(HelloReply other) { |
||||
if (ReferenceEquals(other, null)) { |
||||
return false; |
||||
} |
||||
if (ReferenceEquals(other, this)) { |
||||
return true; |
||||
} |
||||
if (Message != other.Message) return false; |
||||
return true; |
||||
} |
||||
|
||||
public override int GetHashCode() { |
||||
int hash = 1; |
||||
if (Message.Length != 0) hash ^= Message.GetHashCode(); |
||||
return hash; |
||||
} |
||||
|
||||
public override string ToString() { |
||||
return pb::JsonFormatter.ToDiagnosticString(this); |
||||
} |
||||
|
||||
public void WriteTo(pb::CodedOutputStream output) { |
||||
if (Message.Length != 0) { |
||||
output.WriteRawTag(10); |
||||
output.WriteString(Message); |
||||
} |
||||
} |
||||
|
||||
public int CalculateSize() { |
||||
int size = 0; |
||||
if (Message.Length != 0) { |
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); |
||||
} |
||||
return size; |
||||
} |
||||
|
||||
public void MergeFrom(HelloReply other) { |
||||
if (other == null) { |
||||
return; |
||||
} |
||||
if (other.Message.Length != 0) { |
||||
Message = other.Message; |
||||
} |
||||
} |
||||
|
||||
public void MergeFrom(pb::CodedInputStream input) { |
||||
uint tag; |
||||
while ((tag = input.ReadTag()) != 0) { |
||||
switch(tag) { |
||||
default: |
||||
input.SkipLastField(); |
||||
break; |
||||
case 10: { |
||||
Message = input.ReadString(); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
#endregion |
||||
|
||||
} |
||||
|
||||
#endregion Designer generated code |
@ -0,0 +1,143 @@ |
||||
// Generated by the protocol buffer compiler. DO NOT EDIT! |
||||
// source: helloworld.proto |
||||
// Original file comments: |
||||
// Copyright 2015, Google Inc. |
||||
// All rights reserved. |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
// |
||||
#region Designer generated code |
||||
|
||||
using System; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
using Grpc.Core; |
||||
|
||||
namespace Helloworld { |
||||
/// <summary> |
||||
/// The greeting service definition. |
||||
/// </summary> |
||||
public static class Greeter |
||||
{ |
||||
static readonly string __ServiceName = "helloworld.Greeter"; |
||||
|
||||
static readonly Marshaller<global::Helloworld.HelloRequest> __Marshaller_HelloRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom); |
||||
static readonly Marshaller<global::Helloworld.HelloReply> __Marshaller_HelloReply = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom); |
||||
|
||||
static readonly Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply> __Method_SayHello = new Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply>( |
||||
MethodType.Unary, |
||||
__ServiceName, |
||||
"SayHello", |
||||
__Marshaller_HelloRequest, |
||||
__Marshaller_HelloReply); |
||||
|
||||
/// <summary>Service descriptor</summary> |
||||
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor |
||||
{ |
||||
get { return global::Helloworld.HelloworldReflection.Descriptor.Services[0]; } |
||||
} |
||||
|
||||
/// <summary>Base class for server-side implementations of Greeter</summary> |
||||
public abstract class GreeterBase |
||||
{ |
||||
/// <summary> |
||||
/// Sends a greeting |
||||
/// </summary> |
||||
public virtual global::System.Threading.Tasks.Task<global::Helloworld.HelloReply> SayHello(global::Helloworld.HelloRequest request, ServerCallContext context) |
||||
{ |
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "")); |
||||
} |
||||
|
||||
} |
||||
|
||||
/// <summary>Client for Greeter</summary> |
||||
public class GreeterClient : ClientBase<GreeterClient> |
||||
{ |
||||
/// <summary>Creates a new client for Greeter</summary> |
||||
/// <param name="channel">The channel to use to make remote calls.</param> |
||||
public GreeterClient(Channel channel) : base(channel) |
||||
{ |
||||
} |
||||
/// <summary>Creates a new client for Greeter that uses a custom <c>CallInvoker</c>.</summary> |
||||
/// <param name="callInvoker">The callInvoker to use to make remote calls.</param> |
||||
public GreeterClient(CallInvoker callInvoker) : base(callInvoker) |
||||
{ |
||||
} |
||||
/// <summary>Protected parameterless constructor to allow creation of test doubles.</summary> |
||||
protected GreeterClient() : base() |
||||
{ |
||||
} |
||||
/// <summary>Protected constructor to allow creation of configured clients.</summary> |
||||
/// <param name="configuration">The client configuration.</param> |
||||
protected GreeterClient(ClientBaseConfiguration configuration) : base(configuration) |
||||
{ |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Sends a greeting |
||||
/// </summary> |
||||
public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) |
||||
{ |
||||
return SayHello(request, new CallOptions(headers, deadline, cancellationToken)); |
||||
} |
||||
/// <summary> |
||||
/// Sends a greeting |
||||
/// </summary> |
||||
public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, CallOptions options) |
||||
{ |
||||
return CallInvoker.BlockingUnaryCall(__Method_SayHello, null, options, request); |
||||
} |
||||
/// <summary> |
||||
/// Sends a greeting |
||||
/// </summary> |
||||
public virtual AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) |
||||
{ |
||||
return SayHelloAsync(request, new CallOptions(headers, deadline, cancellationToken)); |
||||
} |
||||
/// <summary> |
||||
/// Sends a greeting |
||||
/// </summary> |
||||
public virtual AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, CallOptions options) |
||||
{ |
||||
return CallInvoker.AsyncUnaryCall(__Method_SayHello, null, options, request); |
||||
} |
||||
protected override GreeterClient NewInstance(ClientBaseConfiguration configuration) |
||||
{ |
||||
return new GreeterClient(configuration); |
||||
} |
||||
} |
||||
|
||||
/// <summary>Creates service definition that can be registered with a server</summary> |
||||
public static ServerServiceDefinition BindService(GreeterBase serviceImpl) |
||||
{ |
||||
return ServerServiceDefinition.CreateBuilder() |
||||
.AddMethod(__Method_SayHello, serviceImpl.SayHello).Build(); |
||||
} |
||||
|
||||
} |
||||
} |
||||
#endregion |
@ -0,0 +1,22 @@ |
||||
{ |
||||
"title": "Greeter", |
||||
"version": "1.0.0-*", |
||||
"buildOptions": { |
||||
"debugType": "portable", |
||||
}, |
||||
"dependencies": { |
||||
"Google.Protobuf": "3.0.0-beta3", |
||||
"Grpc": "1.0.0-pre1", |
||||
}, |
||||
"frameworks": { |
||||
"net45": { |
||||
"frameworkAssemblies": { |
||||
"System.Runtime": "", |
||||
"System.IO": "" |
||||
}, |
||||
"dependencies": { |
||||
"Microsoft.NETCore.Platforms": "1.0.1" |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,53 @@ |
||||
// Copyright 2015, Google Inc. |
||||
// All rights reserved. |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
using System; |
||||
using Grpc.Core; |
||||
using Helloworld; |
||||
|
||||
namespace GreeterClient |
||||
{ |
||||
class Program |
||||
{ |
||||
public static void Main(string[] args) |
||||
{ |
||||
Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure); |
||||
|
||||
var client = new Greeter.GreeterClient(channel); |
||||
String user = "you"; |
||||
|
||||
var reply = client.SayHello(new HelloRequest { Name = user }); |
||||
Console.WriteLine("Greeting: " + reply.Message); |
||||
|
||||
channel.ShutdownAsync().Wait(); |
||||
Console.WriteLine("Press any key to exit..."); |
||||
Console.ReadKey(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,26 @@ |
||||
{ |
||||
"title": "GreeterClient", |
||||
"version": "1.0.0-*", |
||||
"buildOptions": { |
||||
"debugType": "portable", |
||||
"emitEntryPoint": "true" |
||||
}, |
||||
"dependencies": { |
||||
"Google.Protobuf": "3.0.0-beta3", |
||||
"Grpc": "1.0.0-pre1", |
||||
"Greeter": { |
||||
"target": "project" |
||||
} |
||||
}, |
||||
"frameworks": { |
||||
"net45": { |
||||
"frameworkAssemblies": { |
||||
"System.Runtime": "", |
||||
"System.IO": "" |
||||
}, |
||||
"dependencies": { |
||||
"Microsoft.NETCore.Platforms": "1.0.1" |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,66 @@ |
||||
// Copyright 2015, Google Inc. |
||||
// All rights reserved. |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
using System; |
||||
using System.Threading.Tasks; |
||||
using Grpc.Core; |
||||
using Helloworld; |
||||
|
||||
namespace GreeterServer |
||||
{ |
||||
class GreeterImpl : Greeter.GreeterBase |
||||
{ |
||||
// Server side handler of the SayHello RPC |
||||
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context) |
||||
{ |
||||
return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); |
||||
} |
||||
} |
||||
|
||||
class Program |
||||
{ |
||||
const int Port = 50051; |
||||
|
||||
public static void Main(string[] args) |
||||
{ |
||||
Server server = new Server |
||||
{ |
||||
Services = { Greeter.BindService(new GreeterImpl()) }, |
||||
Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } |
||||
}; |
||||
server.Start(); |
||||
|
||||
Console.WriteLine("Greeter server listening on port " + Port); |
||||
Console.WriteLine("Press any key to stop the server..."); |
||||
Console.ReadKey(); |
||||
|
||||
server.ShutdownAsync().Wait(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,26 @@ |
||||
{ |
||||
"title": "GreeterServer", |
||||
"version": "1.0.0-*", |
||||
"buildOptions": { |
||||
"debugType": "portable", |
||||
"emitEntryPoint": "true" |
||||
}, |
||||
"dependencies": { |
||||
"Google.Protobuf": "3.0.0-beta3", |
||||
"Grpc": "1.0.0-pre1", |
||||
"Greeter": { |
||||
"target": "project" |
||||
} |
||||
}, |
||||
"frameworks": { |
||||
"net45": { |
||||
"frameworkAssemblies": { |
||||
"System.Runtime": "", |
||||
"System.IO": "" |
||||
}, |
||||
"dependencies": { |
||||
"Microsoft.NETCore.Platforms": "1.0.1" |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,59 @@ |
||||
gRPC in 3 minutes (C#) |
||||
======================== |
||||
|
||||
BACKGROUND |
||||
------------- |
||||
This is a different version of the helloworld example, using the dotnet sdk |
||||
tools to build and run. |
||||
|
||||
For this sample, we've already generated the server and client stubs from [helloworld.proto][]. |
||||
|
||||
Example projects in this directory depend on the [Grpc](https://www.nuget.org/packages/Grpc/) |
||||
and [Google.Protobuf](https://www.nuget.org/packages/Google.Protobuf/) NuGet packages |
||||
which have been already added to the project for you. |
||||
|
||||
The examples in this directory target .NET 4.5 framework, as .NET Core support is |
||||
currently experimental. |
||||
|
||||
PREREQUISITES |
||||
------------- |
||||
|
||||
- The DotNetCore SDK cli. |
||||
|
||||
- The .NET 4.5 framework. |
||||
|
||||
Both are available to download at https://www.microsoft.com/net/download |
||||
|
||||
BUILD |
||||
------- |
||||
|
||||
From the `examples/csharp/helloworld-from-cli` directory: |
||||
|
||||
- `dotnet restore` |
||||
|
||||
- `dotnet build **/project.json` (this will automatically download NuGet dependencies) |
||||
|
||||
Try it! |
||||
------- |
||||
|
||||
- Run the server |
||||
|
||||
``` |
||||
> cd GreeterServer |
||||
> dotnet run |
||||
``` |
||||
|
||||
- Run the client |
||||
|
||||
``` |
||||
> cd GreeterClient |
||||
> dotnet run |
||||
``` |
||||
|
||||
Tutorial |
||||
-------- |
||||
|
||||
You can find a more detailed tutorial about Grpc in [gRPC Basics: C#][] |
||||
|
||||
[helloworld.proto]:../../protos/helloworld.proto |
||||
[gRPC Basics: C#]:http://www.grpc.io/docs/tutorials/basic/csharp.html |
@ -1,8 +1,7 @@ |
||||
{ |
||||
"name": "grpc/grpc-demo", |
||||
"description": "gRPC example for PHP", |
||||
"minimum-stability": "dev", |
||||
"require": { |
||||
"grpc/grpc": "v0.15.2" |
||||
"grpc/grpc": "v1.0.0", |
||||
} |
||||
} |
||||
|
@ -1,6 +1,6 @@ |
||||
#gRPC Basics: PHP sample code |
||||
|
||||
The files in this folder are the samples used in [gRPC Basics: PHP][], |
||||
a detailed tutorial for using gRPC in Ruby. |
||||
a detailed tutorial for using gRPC in PHP. |
||||
|
||||
[gRPC Basics: PHP]:http://www.grpc.io/docs/tutorials/basic/php.html |
||||
|
@ -0,0 +1,219 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPCXX_IMPL_CODEGEN_THRIFT_SERIALIZER_H |
||||
#define GRPCXX_IMPL_CODEGEN_THRIFT_SERIALIZER_H |
||||
|
||||
#include <grpc/impl/codegen/byte_buffer.h> |
||||
#include <grpc/impl/codegen/byte_buffer_reader.h> |
||||
#include <grpc/impl/codegen/slice.h> |
||||
#include <grpc/impl/codegen/slice_buffer.h> |
||||
#include <thrift/protocol/TBinaryProtocol.h> |
||||
#include <thrift/protocol/TCompactProtocol.h> |
||||
#include <thrift/protocol/TProtocolException.h> |
||||
#include <thrift/transport/TBufferTransports.h> |
||||
#include <thrift/transport/TTransportUtils.h> |
||||
#include <boost/make_shared.hpp> |
||||
#include <memory> |
||||
#include <stdexcept> |
||||
#include <string> |
||||
|
||||
namespace apache { |
||||
namespace thrift { |
||||
namespace util { |
||||
|
||||
using apache::thrift::protocol::TBinaryProtocolT; |
||||
using apache::thrift::protocol::TCompactProtocolT; |
||||
using apache::thrift::protocol::TMessageType; |
||||
using apache::thrift::protocol::TNetworkBigEndian; |
||||
using apache::thrift::transport::TMemoryBuffer; |
||||
using apache::thrift::transport::TBufferBase; |
||||
using apache::thrift::transport::TTransport; |
||||
|
||||
template <typename Dummy, typename Protocol> |
||||
class ThriftSerializer { |
||||
public: |
||||
ThriftSerializer() |
||||
: prepared_(false), |
||||
last_deserialized_(false), |
||||
serialize_version_(false) {} |
||||
|
||||
virtual ~ThriftSerializer() {} |
||||
|
||||
// Serialize the passed type into the internal buffer
|
||||
// and returns a pointer to internal buffer and its size
|
||||
template <typename T> |
||||
void Serialize(const T& fields, const uint8_t** serialized_buffer, |
||||
size_t* serialized_len) { |
||||
// prepare or reset buffer
|
||||
if (!prepared_ || last_deserialized_) { |
||||
prepare(); |
||||
} else { |
||||
buffer_->resetBuffer(); |
||||
} |
||||
last_deserialized_ = false; |
||||
|
||||
// if required serialize protocol version
|
||||
if (serialize_version_) { |
||||
protocol_->writeMessageBegin("", TMessageType(0), 0); |
||||
} |
||||
|
||||
// serialize fields into buffer
|
||||
fields.write(protocol_.get()); |
||||
|
||||
// write the end of message
|
||||
if (serialize_version_) { |
||||
protocol_->writeMessageEnd(); |
||||
} |
||||
|
||||
uint8_t* byte_buffer; |
||||
uint32_t byte_buffer_size; |
||||
buffer_->getBuffer(&byte_buffer, &byte_buffer_size); |
||||
*serialized_buffer = byte_buffer; |
||||
*serialized_len = byte_buffer_size; |
||||
} |
||||
|
||||
// Serialize the passed type into the byte buffer
|
||||
template <typename T> |
||||
void Serialize(const T& fields, grpc_byte_buffer** bp) { |
||||
const uint8_t* byte_buffer; |
||||
size_t byte_buffer_size; |
||||
|
||||
Serialize(fields, &byte_buffer, &byte_buffer_size); |
||||
|
||||
gpr_slice slice = gpr_slice_from_copied_buffer( |
||||
reinterpret_cast<const char*>(byte_buffer), byte_buffer_size); |
||||
|
||||
*bp = grpc_raw_byte_buffer_create(&slice, 1); |
||||
|
||||
gpr_slice_unref(slice); |
||||
} |
||||
|
||||
// Deserialize the passed char array into the passed type, returns the number
|
||||
// of bytes that have been consumed from the passed string.
|
||||
template <typename T> |
||||
uint32_t Deserialize(uint8_t* serialized_buffer, size_t length, T* fields) { |
||||
// prepare buffer if necessary
|
||||
if (!prepared_) { |
||||
prepare(); |
||||
} |
||||
last_deserialized_ = true; |
||||
|
||||
// reset buffer transport
|
||||
buffer_->resetBuffer(serialized_buffer, length); |
||||
|
||||
// read the protocol version if necessary
|
||||
if (serialize_version_) { |
||||
std::string name = ""; |
||||
TMessageType mt = static_cast<TMessageType>(0); |
||||
int32_t seq_id = 0; |
||||
protocol_->readMessageBegin(name, mt, seq_id); |
||||
} |
||||
|
||||
// deserialize buffer into fields
|
||||
uint32_t len = fields->read(protocol_.get()); |
||||
|
||||
// read the end of message
|
||||
if (serialize_version_) { |
||||
protocol_->readMessageEnd(); |
||||
} |
||||
|
||||
return len; |
||||
} |
||||
|
||||
// Deserialize the passed byte buffer to passed type, returns the number
|
||||
// of bytes consumed from byte buffer
|
||||
template <typename T> |
||||
uint32_t Deserialize(grpc_byte_buffer* buffer, T* msg) { |
||||
grpc_byte_buffer_reader reader; |
||||
grpc_byte_buffer_reader_init(&reader, buffer); |
||||
|
||||
gpr_slice slice = grpc_byte_buffer_reader_readall(&reader); |
||||
|
||||
uint32_t len = |
||||
Deserialize(GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice), msg); |
||||
|
||||
gpr_slice_unref(slice); |
||||
|
||||
grpc_byte_buffer_reader_destroy(&reader); |
||||
|
||||
return len; |
||||
} |
||||
|
||||
// set serialization version flag
|
||||
void SetSerializeVersion(bool value) { serialize_version_ = value; } |
||||
|
||||
// Set the container size limit to deserialize
|
||||
// This function should be called after buffer_ is initialized
|
||||
void SetContainerSizeLimit(int32_t container_limit) { |
||||
if (!prepared_) { |
||||
prepare(); |
||||
} |
||||
protocol_->setContainerSizeLimit(container_limit); |
||||
} |
||||
|
||||
// Set the string size limit to deserialize
|
||||
// This function should be called after buffer_ is initialized
|
||||
void SetStringSizeLimit(int32_t string_limit) { |
||||
if (!prepared_) { |
||||
prepare(); |
||||
} |
||||
protocol_->setStringSizeLimit(string_limit); |
||||
} |
||||
|
||||
private: |
||||
bool prepared_; |
||||
bool last_deserialized_; |
||||
boost::shared_ptr<TMemoryBuffer> buffer_; |
||||
std::shared_ptr<Protocol> protocol_; |
||||
bool serialize_version_; |
||||
|
||||
void prepare() { |
||||
buffer_ = boost::make_shared<TMemoryBuffer>(); |
||||
// create a protocol for the memory buffer transport
|
||||
protocol_ = std::make_shared<Protocol>(buffer_); |
||||
prepared_ = true; |
||||
} |
||||
|
||||
}; // ThriftSerializer
|
||||
|
||||
typedef ThriftSerializer<void, TBinaryProtocolT<TBufferBase, TNetworkBigEndian>> |
||||
ThriftSerializerBinary; |
||||
typedef ThriftSerializer<void, TCompactProtocolT<TBufferBase>> |
||||
ThriftSerializerCompact; |
||||
|
||||
} // namespace util
|
||||
} // namespace thrift
|
||||
} // namespace apache
|
||||
|
||||
#endif |
@ -0,0 +1,85 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H |
||||
#define GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H |
||||
|
||||
#include <grpc++/impl/codegen/config.h> |
||||
#include <grpc++/impl/codegen/core_codegen_interface.h> |
||||
#include <grpc++/impl/codegen/serialization_traits.h> |
||||
#include <grpc++/impl/codegen/status.h> |
||||
#include <grpc++/impl/codegen/status_code_enum.h> |
||||
#include <grpc++/impl/codegen/thrift_serializer.h> |
||||
#include <grpc/impl/codegen/byte_buffer.h> |
||||
#include <grpc/impl/codegen/byte_buffer_reader.h> |
||||
#include <grpc/impl/codegen/slice.h> |
||||
#include <grpc/impl/codegen/slice_buffer.h> |
||||
#include <cstdint> |
||||
#include <cstdlib> |
||||
|
||||
namespace grpc { |
||||
|
||||
using apache::thrift::util::ThriftSerializerCompact; |
||||
|
||||
template <class T> |
||||
class SerializationTraits<T, typename std::enable_if<std::is_base_of< |
||||
apache::thrift::TBase, T>::value>::type> { |
||||
public: |
||||
static Status Serialize(const T& msg, grpc_byte_buffer** bp, |
||||
bool* own_buffer) { |
||||
*own_buffer = true; |
||||
|
||||
ThriftSerializerCompact serializer; |
||||
serializer.Serialize(msg, bp); |
||||
|
||||
return Status(StatusCode::OK, "ok"); |
||||
} |
||||
|
||||
static Status Deserialize(grpc_byte_buffer* buffer, T* msg, |
||||
int max_message_size) { |
||||
if (!buffer) { |
||||
return Status(StatusCode::INTERNAL, "No payload"); |
||||
} |
||||
|
||||
ThriftSerializerCompact deserializer; |
||||
deserializer.Deserialize(buffer, msg); |
||||
|
||||
grpc_byte_buffer_destroy(buffer); |
||||
|
||||
return Status(StatusCode::OK, "ok"); |
||||
} |
||||
}; |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,112 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include <string.h> |
||||
|
||||
#include "src/core/lib/channel/channel_stack.h" |
||||
#include "src/cpp/common/channel_filter.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
// MetadataBatch
|
||||
|
||||
grpc_linked_mdelem *MetadataBatch::AddMetadata(const string &key, |
||||
const string &value) { |
||||
grpc_linked_mdelem *storage = new grpc_linked_mdelem; |
||||
memset(storage, 0, sizeof(grpc_linked_mdelem)); |
||||
storage->md = grpc_mdelem_from_strings(key.c_str(), value.c_str()); |
||||
grpc_metadata_batch_link_head(batch_, storage); |
||||
return storage; |
||||
} |
||||
|
||||
// ChannelData
|
||||
|
||||
void ChannelData::StartTransportOp(grpc_exec_ctx *exec_ctx, |
||||
grpc_channel_element *elem, |
||||
TransportOp *op) { |
||||
grpc_channel_next_op(exec_ctx, elem, op->op()); |
||||
} |
||||
|
||||
// CallData
|
||||
|
||||
void CallData::StartTransportStreamOp(grpc_exec_ctx *exec_ctx, |
||||
grpc_call_element *elem, |
||||
TransportStreamOp *op) { |
||||
grpc_call_next_op(exec_ctx, elem, op->op()); |
||||
} |
||||
|
||||
void CallData::SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx, |
||||
grpc_call_element *elem, |
||||
grpc_polling_entity *pollent) { |
||||
grpc_call_stack_ignore_set_pollset_or_pollset_set(exec_ctx, elem, pollent); |
||||
} |
||||
|
||||
char *CallData::GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { |
||||
return grpc_call_next_get_peer(exec_ctx, elem); |
||||
} |
||||
|
||||
// internal code used by RegisterChannelFilter()
|
||||
|
||||
namespace internal { |
||||
|
||||
// Note: Implicitly initialized to nullptr due to static lifetime.
|
||||
std::vector<FilterRecord> *channel_filters; |
||||
|
||||
namespace { |
||||
|
||||
bool MaybeAddFilter(grpc_channel_stack_builder *builder, void *arg) { |
||||
const FilterRecord &filter = *(FilterRecord *)arg; |
||||
if (filter.include_filter) { |
||||
const grpc_channel_args *args = |
||||
grpc_channel_stack_builder_get_channel_arguments(builder); |
||||
if (!filter.include_filter(*args)) return true; |
||||
} |
||||
return grpc_channel_stack_builder_prepend_filter(builder, &filter.filter, |
||||
nullptr, nullptr); |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
void ChannelFilterPluginInit() { |
||||
for (size_t i = 0; i < channel_filters->size(); ++i) { |
||||
FilterRecord &filter = (*channel_filters)[i]; |
||||
grpc_channel_init_register_stage(filter.stack_type, filter.priority, |
||||
MaybeAddFilter, (void *)&filter); |
||||
} |
||||
} |
||||
|
||||
void ChannelFilterPluginShutdown() {} |
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace grpc
|
@ -0,0 +1,389 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPCXX_CHANNEL_FILTER_H |
||||
#define GRPCXX_CHANNEL_FILTER_H |
||||
|
||||
#include <grpc++/impl/codegen/config.h> |
||||
#include <grpc/grpc.h> |
||||
#include <grpc/impl/codegen/alloc.h> |
||||
|
||||
#include <functional> |
||||
#include <vector> |
||||
|
||||
#include "src/core/lib/channel/channel_stack.h" |
||||
#include "src/core/lib/surface/channel_init.h" |
||||
#include "src/core/lib/transport/metadata_batch.h" |
||||
|
||||
/// An interface to define filters.
|
||||
///
|
||||
/// To define a filter, implement a subclass of each of \c CallData and
|
||||
/// \c ChannelData. Then register the filter using something like this:
|
||||
/// \code{.cpp}
|
||||
/// RegisterChannelFilter<MyChannelDataSubclass, MyCallDataSubclass>(
|
||||
/// "name-of-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr);
|
||||
/// \endcode
|
||||
|
||||
/// Forward declaration to avoid including the file
|
||||
/// "src/core/lib/security/context/security_context.h"
|
||||
struct grpc_client_security_context; |
||||
struct grpc_server_security_context; |
||||
|
||||
namespace grpc { |
||||
|
||||
/// A C++ wrapper for the \c grpc_metadata_batch struct.
|
||||
class MetadataBatch { |
||||
public: |
||||
/// Borrows a pointer to \a batch, but does NOT take ownership.
|
||||
/// The caller must ensure that \a batch continues to exist for as
|
||||
/// long as the MetadataBatch object does.
|
||||
explicit MetadataBatch(grpc_metadata_batch *batch) : batch_(batch) {} |
||||
|
||||
grpc_metadata_batch *batch() const { return batch_; } |
||||
|
||||
/// Adds metadata and returns the newly allocated storage.
|
||||
/// The caller takes ownership of the result, which must exist for the
|
||||
/// lifetime of the gRPC call.
|
||||
grpc_linked_mdelem *AddMetadata(const string &key, const string &value); |
||||
|
||||
class const_iterator : public std::iterator<std::bidirectional_iterator_tag, |
||||
const grpc_mdelem> { |
||||
public: |
||||
const grpc_mdelem &operator*() const { return *elem_->md; } |
||||
const grpc_mdelem *operator->() const { return elem_->md; } |
||||
|
||||
const_iterator &operator++() { |
||||
elem_ = elem_->next; |
||||
return *this; |
||||
} |
||||
const_iterator operator++(int) { |
||||
const_iterator tmp(*this); |
||||
operator++(); |
||||
return tmp; |
||||
} |
||||
const_iterator &operator--() { |
||||
elem_ = elem_->prev; |
||||
return *this; |
||||
} |
||||
const_iterator operator--(int) { |
||||
const_iterator tmp(*this); |
||||
operator--(); |
||||
return tmp; |
||||
} |
||||
|
||||
bool operator==(const const_iterator &other) const { |
||||
return elem_ == other.elem_; |
||||
} |
||||
bool operator!=(const const_iterator &other) const { |
||||
return elem_ != other.elem_; |
||||
} |
||||
|
||||
private: |
||||
friend class MetadataBatch; |
||||
explicit const_iterator(grpc_linked_mdelem *elem) : elem_(elem) {} |
||||
|
||||
grpc_linked_mdelem *elem_; |
||||
}; |
||||
|
||||
const_iterator begin() const { return const_iterator(batch_->list.head); } |
||||
const_iterator end() const { return const_iterator(nullptr); } |
||||
|
||||
private: |
||||
grpc_metadata_batch *batch_; // Not owned.
|
||||
}; |
||||
|
||||
/// A C++ wrapper for the \c grpc_transport_op struct.
|
||||
class TransportOp { |
||||
public: |
||||
/// Borrows a pointer to \a op, but does NOT take ownership.
|
||||
/// The caller must ensure that \a op continues to exist for as
|
||||
/// long as the TransportOp object does.
|
||||
explicit TransportOp(grpc_transport_op *op) : op_(op) {} |
||||
|
||||
grpc_transport_op *op() const { return op_; } |
||||
|
||||
// TODO(roth): Add a C++ wrapper for grpc_error?
|
||||
grpc_error *disconnect_with_error() const { |
||||
return op_->disconnect_with_error; |
||||
} |
||||
bool send_goaway() const { return op_->send_goaway; } |
||||
|
||||
// TODO(roth): Add methods for additional fields as needed.
|
||||
|
||||
private: |
||||
grpc_transport_op *op_; // Not owned.
|
||||
}; |
||||
|
||||
/// A C++ wrapper for the \c grpc_transport_stream_op struct.
|
||||
class TransportStreamOp { |
||||
public: |
||||
/// Borrows a pointer to \a op, but does NOT take ownership.
|
||||
/// The caller must ensure that \a op continues to exist for as
|
||||
/// long as the TransportStreamOp object does.
|
||||
explicit TransportStreamOp(grpc_transport_stream_op *op) |
||||
: op_(op), |
||||
send_initial_metadata_(op->send_initial_metadata), |
||||
send_trailing_metadata_(op->send_trailing_metadata), |
||||
recv_initial_metadata_(op->recv_initial_metadata), |
||||
recv_trailing_metadata_(op->recv_trailing_metadata) {} |
||||
|
||||
grpc_transport_stream_op *op() const { return op_; } |
||||
|
||||
grpc_closure *on_complete() const { return op_->on_complete; } |
||||
void set_on_complete(grpc_closure *closure) { op_->on_complete = closure; } |
||||
|
||||
MetadataBatch *send_initial_metadata() { |
||||
return op_->send_initial_metadata == nullptr ? nullptr |
||||
: &send_initial_metadata_; |
||||
} |
||||
MetadataBatch *send_trailing_metadata() { |
||||
return op_->send_trailing_metadata == nullptr ? nullptr |
||||
: &send_trailing_metadata_; |
||||
} |
||||
MetadataBatch *recv_initial_metadata() { |
||||
return op_->recv_initial_metadata == nullptr ? nullptr |
||||
: &recv_initial_metadata_; |
||||
} |
||||
MetadataBatch *recv_trailing_metadata() { |
||||
return op_->recv_trailing_metadata == nullptr ? nullptr |
||||
: &recv_trailing_metadata_; |
||||
} |
||||
|
||||
uint32_t *send_initial_metadata_flags() const { |
||||
return &op_->send_initial_metadata_flags; |
||||
} |
||||
|
||||
grpc_closure *recv_initial_metadata_ready() const { |
||||
return op_->recv_initial_metadata_ready; |
||||
} |
||||
void set_recv_initial_metadata_ready(grpc_closure *closure) { |
||||
op_->recv_initial_metadata_ready = closure; |
||||
} |
||||
|
||||
grpc_byte_stream *send_message() const { return op_->send_message; } |
||||
void set_send_message(grpc_byte_stream *send_message) { |
||||
op_->send_message = send_message; |
||||
} |
||||
|
||||
/// To be called only on clients and servers, respectively.
|
||||
grpc_client_security_context *client_security_context() const { |
||||
return (grpc_client_security_context *)op_->context[GRPC_CONTEXT_SECURITY] |
||||
.value; |
||||
} |
||||
grpc_server_security_context *server_security_context() const { |
||||
return (grpc_server_security_context *)op_->context[GRPC_CONTEXT_SECURITY] |
||||
.value; |
||||
} |
||||
|
||||
census_context *get_census_context() const { |
||||
return (census_context *)op_->context[GRPC_CONTEXT_TRACING].value; |
||||
} |
||||
|
||||
private: |
||||
grpc_transport_stream_op *op_; // Not owned.
|
||||
MetadataBatch send_initial_metadata_; |
||||
MetadataBatch send_trailing_metadata_; |
||||
MetadataBatch recv_initial_metadata_; |
||||
MetadataBatch recv_trailing_metadata_; |
||||
}; |
||||
|
||||
/// Represents channel data.
|
||||
class ChannelData { |
||||
public: |
||||
virtual ~ChannelData() { |
||||
if (peer_) gpr_free((void *)peer_); |
||||
} |
||||
|
||||
/// Caller does NOT take ownership of result.
|
||||
const char *peer() const { return peer_; } |
||||
|
||||
// TODO(roth): Find a way to avoid passing elem into these methods.
|
||||
virtual void StartTransportOp(grpc_exec_ctx *exec_ctx, |
||||
grpc_channel_element *elem, TransportOp *op); |
||||
|
||||
protected: |
||||
/// Takes ownership of \a peer.
|
||||
ChannelData(const grpc_channel_args &args, const char *peer) : peer_(peer) {} |
||||
|
||||
private: |
||||
const char *peer_; |
||||
}; |
||||
|
||||
/// Represents call data.
|
||||
class CallData { |
||||
public: |
||||
virtual ~CallData() {} |
||||
|
||||
/// Initializes the call data.
|
||||
virtual grpc_error *Init() { return GRPC_ERROR_NONE; } |
||||
|
||||
// TODO(roth): Find a way to avoid passing elem into these methods.
|
||||
|
||||
/// Starts a new stream operation.
|
||||
virtual void StartTransportStreamOp(grpc_exec_ctx *exec_ctx, |
||||
grpc_call_element *elem, |
||||
TransportStreamOp *op); |
||||
|
||||
/// Sets a pollset or pollset set.
|
||||
virtual void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx, |
||||
grpc_call_element *elem, |
||||
grpc_polling_entity *pollent); |
||||
|
||||
/// Gets the peer name.
|
||||
virtual char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem); |
||||
|
||||
protected: |
||||
explicit CallData(const ChannelData &) {} |
||||
}; |
||||
|
||||
namespace internal { |
||||
|
||||
// Defines static members for passing to C core.
|
||||
// Members of this class correspond to the members of the C
|
||||
// grpc_channel_filter struct.
|
||||
template <typename ChannelDataType, typename CallDataType> |
||||
class ChannelFilter GRPC_FINAL { |
||||
public: |
||||
static const size_t channel_data_size = sizeof(ChannelDataType); |
||||
|
||||
static void InitChannelElement(grpc_exec_ctx *exec_ctx, |
||||
grpc_channel_element *elem, |
||||
grpc_channel_element_args *args) { |
||||
const char *peer = |
||||
args->optional_transport |
||||
? grpc_transport_get_peer(exec_ctx, args->optional_transport) |
||||
: nullptr; |
||||
// Construct the object in the already-allocated memory.
|
||||
new (elem->channel_data) ChannelDataType(*args->channel_args, peer); |
||||
} |
||||
|
||||
static void DestroyChannelElement(grpc_exec_ctx *exec_ctx, |
||||
grpc_channel_element *elem) { |
||||
reinterpret_cast<ChannelDataType *>(elem->channel_data)->~ChannelDataType(); |
||||
} |
||||
|
||||
static void StartTransportOp(grpc_exec_ctx *exec_ctx, |
||||
grpc_channel_element *elem, |
||||
grpc_transport_op *op) { |
||||
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data; |
||||
TransportOp op_wrapper(op); |
||||
channel_data->StartTransportOp(exec_ctx, elem, &op_wrapper); |
||||
} |
||||
|
||||
static const size_t call_data_size = sizeof(CallDataType); |
||||
|
||||
static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx, |
||||
grpc_call_element *elem, |
||||
grpc_call_element_args *args) { |
||||
const ChannelDataType &channel_data = |
||||
*(ChannelDataType *)elem->channel_data; |
||||
// Construct the object in the already-allocated memory.
|
||||
CallDataType *call_data = new (elem->call_data) CallDataType(channel_data); |
||||
return call_data->Init(); |
||||
} |
||||
|
||||
static void DestroyCallElement(grpc_exec_ctx *exec_ctx, |
||||
grpc_call_element *elem, |
||||
const grpc_call_final_info *final_info, |
||||
void *and_free_memory) { |
||||
reinterpret_cast<CallDataType *>(elem->call_data)->~CallDataType(); |
||||
} |
||||
|
||||
static void StartTransportStreamOp(grpc_exec_ctx *exec_ctx, |
||||
grpc_call_element *elem, |
||||
grpc_transport_stream_op *op) { |
||||
CallDataType *call_data = (CallDataType *)elem->call_data; |
||||
TransportStreamOp op_wrapper(op); |
||||
call_data->StartTransportStreamOp(exec_ctx, elem, &op_wrapper); |
||||
} |
||||
|
||||
static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx, |
||||
grpc_call_element *elem, |
||||
grpc_polling_entity *pollent) { |
||||
CallDataType *call_data = (CallDataType *)elem->call_data; |
||||
call_data->SetPollsetOrPollsetSet(exec_ctx, elem, pollent); |
||||
} |
||||
|
||||
static char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { |
||||
CallDataType *call_data = (CallDataType *)elem->call_data; |
||||
return call_data->GetPeer(exec_ctx, elem); |
||||
} |
||||
}; |
||||
|
||||
struct FilterRecord { |
||||
grpc_channel_stack_type stack_type; |
||||
int priority; |
||||
std::function<bool(const grpc_channel_args &)> include_filter; |
||||
grpc_channel_filter filter; |
||||
}; |
||||
extern std::vector<FilterRecord> *channel_filters; |
||||
|
||||
void ChannelFilterPluginInit(); |
||||
void ChannelFilterPluginShutdown(); |
||||
|
||||
} // namespace internal
|
||||
|
||||
/// Registers a new filter.
|
||||
/// Must be called by only one thread at a time.
|
||||
/// The \a include_filter argument specifies a function that will be called
|
||||
/// to determine at run-time whether or not to add the filter. If the
|
||||
/// value is nullptr, the filter will be added unconditionally.
|
||||
template <typename ChannelDataType, typename CallDataType> |
||||
void RegisterChannelFilter( |
||||
const char *name, grpc_channel_stack_type stack_type, int priority, |
||||
std::function<bool(const grpc_channel_args &)> include_filter) { |
||||
// If we haven't been called before, initialize channel_filters and
|
||||
// call grpc_register_plugin().
|
||||
if (internal::channel_filters == nullptr) { |
||||
grpc_register_plugin(internal::ChannelFilterPluginInit, |
||||
internal::ChannelFilterPluginShutdown); |
||||
internal::channel_filters = new std::vector<internal::FilterRecord>(); |
||||
} |
||||
// Add an entry to channel_filters. The filter will be added when the
|
||||
// C-core initialization code calls ChannelFilterPluginInit().
|
||||
typedef internal::ChannelFilter<ChannelDataType, CallDataType> FilterType; |
||||
internal::FilterRecord filter_record = { |
||||
stack_type, |
||||
priority, |
||||
include_filter, |
||||
{FilterType::StartTransportStreamOp, FilterType::StartTransportOp, |
||||
FilterType::call_data_size, FilterType::InitCallElement, |
||||
FilterType::SetPollsetOrPollsetSet, FilterType::DestroyCallElement, |
||||
FilterType::channel_data_size, FilterType::InitChannelElement, |
||||
FilterType::DestroyChannelElement, FilterType::GetPeer, name}}; |
||||
internal::channel_filters->push_back(filter_record); |
||||
} |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCXX_CHANNEL_FILTER_H
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue