aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/csharp
diff options
context:
space:
mode:
Diffstat (limited to 'src/csharp')
-rw-r--r--src/csharp/Grpc.Core.Tests/ClientServerTest.cs28
-rw-r--r--src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj4
-rw-r--r--src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs2
-rw-r--r--src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs62
-rw-r--r--src/csharp/Grpc.Core.Tests/PInvokeTest.cs35
-rw-r--r--src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs10
-rw-r--r--src/csharp/Grpc.Core.Tests/ServerTest.cs3
-rw-r--r--src/csharp/Grpc.Core.Tests/TimespecTest.cs1
-rw-r--r--src/csharp/Grpc.Core/Call.cs57
-rw-r--r--src/csharp/Grpc.Core/Calls.cs36
-rw-r--r--src/csharp/Grpc.Core/Channel.cs5
-rw-r--r--src/csharp/Grpc.Core/ChannelArgs.cs47
-rw-r--r--src/csharp/Grpc.Core/ClientStreamingAsyncResult.cs1
-rw-r--r--src/csharp/Grpc.Core/Credentials.cs4
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.csproj17
-rw-r--r--src/csharp/Grpc.Core/GrpcEnvironment.cs8
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCall.cs49
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCallBase.cs18
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCompletion.cs1
-rw-r--r--src/csharp/Grpc.Core/Internal/BatchContextSafeHandleNotOwned.cs8
-rw-r--r--src/csharp/Grpc.Core/Internal/CallSafeHandle.cs40
-rw-r--r--src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs1
-rw-r--r--src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs1
-rw-r--r--src/csharp/Grpc.Core/Internal/Enums.cs1
-rw-r--r--src/csharp/Grpc.Core/Internal/GrpcLog.cs4
-rw-r--r--src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs17
-rw-r--r--src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs72
-rw-r--r--src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs1
-rw-r--r--src/csharp/Grpc.Core/Internal/ServerCallHandler.cs (renamed from src/csharp/Grpc.Core/ServerCallHandler.cs)9
-rw-r--r--src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs68
-rw-r--r--src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs13
-rw-r--r--src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs1
-rw-r--r--src/csharp/Grpc.Core/Internal/Timespec.cs11
-rw-r--r--src/csharp/Grpc.Core/Marshaller.cs20
-rw-r--r--src/csharp/Grpc.Core/Metadata.cs126
-rw-r--r--src/csharp/Grpc.Core/Method.cs1
-rw-r--r--src/csharp/Grpc.Core/OperationFailedException.cs1
-rw-r--r--src/csharp/Grpc.Core/Properties/AssemblyInfo.cs28
-rw-r--r--src/csharp/Grpc.Core/RpcException.cs4
-rw-r--r--src/csharp/Grpc.Core/Server.cs49
-rw-r--r--src/csharp/Grpc.Core/ServerCalls.cs11
-rw-r--r--src/csharp/Grpc.Core/ServerCredentials.cs109
-rw-r--r--src/csharp/Grpc.Core/ServerServiceDefinition.cs33
-rw-r--r--src/csharp/Grpc.Core/StatusCode.cs5
-rw-r--r--src/csharp/Grpc.Core/Stub/AbstractStub.cs73
-rw-r--r--src/csharp/Grpc.Core/Stub/StubConfiguration.cs64
-rw-r--r--src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs7
-rw-r--r--src/csharp/Grpc.Core/Utils/ExceptionHelper.cs4
-rw-r--r--src/csharp/Grpc.Core/Utils/Preconditions.cs9
-rw-r--r--src/csharp/Grpc.Core/Utils/RecordingObserver.cs4
-rw-r--r--src/csharp/Grpc.Core/Utils/RecordingQueue.cs5
-rw-r--r--src/csharp/Grpc.Core/packages.config4
-rw-r--r--src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs28
-rw-r--r--src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs24
-rw-r--r--src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs10
-rw-r--r--src/csharp/Grpc.Examples/MathExamples.cs21
-rw-r--r--src/csharp/Grpc.Examples/MathGrpc.cs83
-rw-r--r--src/csharp/Grpc.Examples/MathServiceImpl.cs13
-rw-r--r--src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs28
-rw-r--r--src/csharp/Grpc.Examples/Settings.StyleCop10
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs10
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs10
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj11
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropClient.cs31
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs12
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropServer.cs16
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs10
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Settings.StyleCop11
-rw-r--r--src/csharp/Grpc.IntegrationTesting/TestCredentials.cs84
-rw-r--r--src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs120
-rw-r--r--src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs33
-rw-r--r--src/csharp/Grpc.IntegrationTesting/packages.config1
-rw-r--r--src/csharp/Settings.StyleCop509
-rw-r--r--src/csharp/ext/grpc_csharp_ext.c197
74 files changed, 1884 insertions, 580 deletions
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index 39be35c219..3da9e33e53 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -46,6 +46,8 @@ namespace Grpc.Core.Tests
{
string host = "localhost";
+ string serviceName = "/tests.Test";
+
Method<string, string> unaryEchoStringMethod = new Method<string, string>(
MethodType.Unary,
"/tests.Test/UnaryEchoString",
@@ -69,15 +71,15 @@ namespace Grpc.Core.Tests
{
Server server = new Server();
server.AddServiceDefinition(
- ServerServiceDefinition.CreateBuilder("someService")
+ ServerServiceDefinition.CreateBuilder(serviceName)
.AddMethod(unaryEchoStringMethod, HandleUnaryEchoString).Build());
- int port = server.AddPort(host + ":0");
+ int port = server.AddListeningPort(host + ":0");
server.Start();
using (Channel channel = new Channel(host + ":" + port))
{
- var call = new Call<string, string>(unaryEchoStringMethod, channel);
+ var call = new Call<string, string>(serviceName, unaryEchoStringMethod, channel, Metadata.Empty);
Assert.AreEqual("ABC", Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken)));
@@ -92,15 +94,15 @@ namespace Grpc.Core.Tests
{
Server server = new Server();
server.AddServiceDefinition(
- ServerServiceDefinition.CreateBuilder("someService")
+ ServerServiceDefinition.CreateBuilder(serviceName)
.AddMethod(unaryEchoStringMethod, HandleUnaryEchoString).Build());
- int port = server.AddPort(host + ":0");
+ int port = server.AddListeningPort(host + ":0");
server.Start();
using (Channel channel = new Channel(host + ":" + port))
{
- var call = new Call<string, string>(unaryEchoStringMethod, channel);
+ var call = new Call<string, string>(serviceName, unaryEchoStringMethod, channel, Metadata.Empty);
BenchmarkUtil.RunBenchmark(100, 1000,
() => { Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken)); });
}
@@ -113,19 +115,22 @@ namespace Grpc.Core.Tests
{
Server server = new Server();
server.AddServiceDefinition(
- ServerServiceDefinition.CreateBuilder("someService").Build());
+ ServerServiceDefinition.CreateBuilder(serviceName).Build());
- int port = server.AddPort(host + ":0");
+ int port = server.AddListeningPort(host + ":0");
server.Start();
using (Channel channel = new Channel(host + ":" + port))
{
- var call = new Call<string, string>(unaryEchoStringMethod, channel);
+ var call = new Call<string, string>(serviceName, unaryEchoStringMethod, channel, Metadata.Empty);
- try {
+ try
+ {
Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken));
Assert.Fail();
- } catch(RpcException e) {
+ }
+ catch (RpcException e)
+ {
Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
}
}
@@ -140,4 +145,3 @@ namespace Grpc.Core.Tests
}
}
}
-
diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
index a365320f05..eac8d16fb1 100644
--- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
+++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
@@ -42,6 +42,7 @@
<Compile Include="GrpcEnvironmentTest.cs" />
<Compile Include="TimespecTest.cs" />
<Compile Include="PInvokeTest.cs" />
+ <Compile Include="Internal\MetadataArraySafeHandleTest.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
@@ -56,4 +57,7 @@
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
+ <ItemGroup>
+ <Folder Include="Internal\" />
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
index 596918c231..6a132a5b22 100644
--- a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
+++ b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
@@ -68,7 +68,7 @@ namespace Grpc.Core.Tests
var tp2 = GrpcEnvironment.ThreadPool;
GrpcEnvironment.Shutdown();
- Assert.IsFalse(Object.ReferenceEquals(tp1, tp2));
+ Assert.IsFalse(object.ReferenceEquals(tp1, tp2));
}
}
}
diff --git a/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs b/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs
new file mode 100644
index 0000000000..2f6013483d
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs
@@ -0,0 +1,62 @@
+#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 Grpc.Core;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+
+namespace Grpc.Core.Internal.Tests
+{
+ public class MetadataArraySafeHandleTest
+ {
+ [Test]
+ public void CreateEmptyAndDestroy()
+ {
+ var metadata = Metadata.CreateBuilder().Build();
+ var nativeMetadata = MetadataArraySafeHandle.Create(metadata);
+ nativeMetadata.Dispose();
+ }
+
+ [Test]
+ public void CreateAndDestroy()
+ {
+ var metadata = Metadata.CreateBuilder()
+ .Add(new Metadata.MetadataEntry("host", "somehost"))
+ .Add(new Metadata.MetadataEntry("header2", "header value")).Build();
+ var nativeMetadata = MetadataArraySafeHandle.Create(metadata);
+ nativeMetadata.Dispose();
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
index 9db08d2f02..3beffc3955 100644
--- a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
+++ b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
@@ -33,13 +33,13 @@
using System;
using System.Diagnostics;
+using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
using NUnit.Framework;
-using System.Runtime.InteropServices;
namespace Grpc.Core.Tests
{
@@ -73,14 +73,13 @@ namespace Grpc.Core.Tests
{
BenchmarkUtil.RunBenchmark(
100000, 1000000,
- () => {
+ () =>
+ {
CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create();
cq.Dispose();
- }
- );
+ });
}
-
/// <summary>
/// Approximate results:
/// (~80ns Mono Linux)
@@ -94,10 +93,10 @@ namespace Grpc.Core.Tests
counter = 0;
BenchmarkUtil.RunBenchmark(
1000000, 10000000,
- () => {
+ () =>
+ {
grpcsharp_test_callback(handler);
- }
- );
+ });
Assert.AreNotEqual(0, counter);
}
@@ -113,10 +112,10 @@ namespace Grpc.Core.Tests
counter = 0;
BenchmarkUtil.RunBenchmark(
10000, 10000,
- () => {
- grpcsharp_test_callback(new CompletionCallbackDelegate(Handler));
- }
- );
+ () =>
+ {
+ grpcsharp_test_callback(new CompletionCallbackDelegate(Handler));
+ });
Assert.AreNotEqual(0, counter);
}
@@ -129,15 +128,15 @@ namespace Grpc.Core.Tests
{
BenchmarkUtil.RunBenchmark(
1000000, 100000000,
- () => {
+ () =>
+ {
grpcsharp_test_nop(IntPtr.Zero);
- }
- );
+ });
}
- private void Handler(GRPCOpError op, IntPtr ptr) {
- counter ++;
+ private void Handler(GRPCOpError op, IntPtr ptr)
+ {
+ counter++;
}
}
}
-
diff --git a/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs
index 499d931d2a..e4328806ad 100644
--- a/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs
@@ -1,8 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
[assembly: AssemblyTitle("Grpc.Core.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
@@ -11,12 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
diff --git a/src/csharp/Grpc.Core.Tests/ServerTest.cs b/src/csharp/Grpc.Core.Tests/ServerTest.cs
index dd30366f6a..2a1855da67 100644
--- a/src/csharp/Grpc.Core.Tests/ServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ServerTest.cs
@@ -47,12 +47,11 @@ namespace Grpc.Core.Tests
GrpcEnvironment.Initialize();
Server server = new Server();
- server.AddPort("localhost:0");
+ server.AddListeningPort("localhost:0");
server.Start();
server.ShutdownAsync().Wait();
GrpcEnvironment.Shutdown();
}
-
}
}
diff --git a/src/csharp/Grpc.Core.Tests/TimespecTest.cs b/src/csharp/Grpc.Core.Tests/TimespecTest.cs
index 0ca84ec44b..f5bae6d935 100644
--- a/src/csharp/Grpc.Core.Tests/TimespecTest.cs
+++ b/src/csharp/Grpc.Core.Tests/TimespecTest.cs
@@ -86,4 +86,3 @@ namespace Grpc.Core.Internal.Tests
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Call.cs b/src/csharp/Grpc.Core/Call.cs
index 72dca68895..fe5f40f5e9 100644
--- a/src/csharp/Grpc.Core/Call.cs
+++ b/src/csharp/Grpc.Core/Call.cs
@@ -33,33 +33,25 @@
using System;
using Grpc.Core.Internal;
+using Grpc.Core.Utils;
namespace Grpc.Core
{
public class Call<TRequest, TResponse>
{
- readonly string methodName;
- readonly Func<TRequest, byte[]> requestSerializer;
- readonly Func<byte[], TResponse> responseDeserializer;
+ readonly string name;
+ readonly Marshaller<TRequest> requestMarshaller;
+ readonly Marshaller<TResponse> responseMarshaller;
readonly Channel channel;
+ readonly Metadata headers;
- public Call(string methodName,
- Func<TRequest, byte[]> requestSerializer,
- Func<byte[], TResponse> responseDeserializer,
- TimeSpan timeout,
- Channel channel) {
- this.methodName = methodName;
- this.requestSerializer = requestSerializer;
- this.responseDeserializer = responseDeserializer;
- this.channel = channel;
- }
-
- public Call(Method<TRequest, TResponse> method, Channel channel)
+ public Call(string serviceName, Method<TRequest, TResponse> method, Channel channel, Metadata headers)
{
- this.methodName = method.Name;
- this.requestSerializer = method.RequestMarshaller.Serializer;
- this.responseDeserializer = method.ResponseMarshaller.Deserializer;
- this.channel = channel;
+ this.name = Preconditions.CheckNotNull(serviceName) + "/" + method.Name;
+ this.requestMarshaller = method.RequestMarshaller;
+ this.responseMarshaller = method.ResponseMarshaller;
+ this.channel = Preconditions.CheckNotNull(channel);
+ this.headers = Preconditions.CheckNotNull(headers);
}
public Channel Channel
@@ -70,29 +62,42 @@ namespace Grpc.Core
}
}
- public string MethodName
+ /// <summary>
+ /// Full methods name including the service name.
+ /// </summary>
+ public string Name
{
get
{
- return this.methodName;
+ return name;
}
}
- public Func<TRequest, byte[]> RequestSerializer
+ /// <summary>
+ /// Headers to send at the beginning of the call.
+ /// </summary>
+ public Metadata Headers
{
get
{
- return this.requestSerializer;
+ return headers;
}
}
- public Func<byte[], TResponse> ResponseDeserializer
+ public Marshaller<TRequest> RequestMarshaller
{
get
{
- return this.responseDeserializer;
+ return requestMarshaller;
+ }
+ }
+
+ public Marshaller<TResponse> ResponseMarshaller
+ {
+ get
+ {
+ return responseMarshaller;
}
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Calls.cs b/src/csharp/Grpc.Core/Calls.cs
index ee2208e5c2..280387b323 100644
--- a/src/csharp/Grpc.Core/Calls.cs
+++ b/src/csharp/Grpc.Core/Calls.cs
@@ -38,8 +38,6 @@ using Grpc.Core.Internal;
namespace Grpc.Core
{
- // NOTE: this class is work-in-progress
-
/// <summary>
/// Helper methods for generated stubs to make RPC calls.
/// </summary>
@@ -47,30 +45,29 @@ namespace Grpc.Core
{
public static TResponse BlockingUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
{
- var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
- return asyncCall.UnaryCall(call.Channel, call.MethodName, req);
+ var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
+ return asyncCall.UnaryCall(call.Channel, call.Name, req, call.Headers);
}
public static async Task<TResponse> AsyncUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
{
- var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
- asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName);
- return await asyncCall.UnaryCallAsync(req);
+ var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
+ asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
+ return await asyncCall.UnaryCallAsync(req, call.Headers);
}
public static void AsyncServerStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, IObserver<TResponse> outputs, CancellationToken token)
{
- var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
-
- asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName);
- asyncCall.StartServerStreamingCall(req, outputs);
+ var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
+ asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
+ asyncCall.StartServerStreamingCall(req, outputs, call.Headers);
}
public static ClientStreamingAsyncResult<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, CancellationToken token)
{
- var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
- asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName);
- var task = asyncCall.ClientStreamingCallAsync();
+ var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
+ asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
+ var task = asyncCall.ClientStreamingCallAsync(call.Headers);
var inputs = new ClientStreamingInputObserver<TRequest, TResponse>(asyncCall);
return new ClientStreamingAsyncResult<TRequest, TResponse>(task, inputs);
}
@@ -82,16 +79,15 @@ namespace Grpc.Core
public static IObserver<TRequest> DuplexStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, IObserver<TResponse> outputs, CancellationToken token)
{
- var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
- asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName);
-
- asyncCall.StartDuplexStreamingCall(outputs);
+ var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
+ asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
+ asyncCall.StartDuplexStreamingCall(outputs, call.Headers);
return new ClientStreamingInputObserver<TRequest, TResponse>(asyncCall);
}
- private static CompletionQueueSafeHandle GetCompletionQueue() {
+ private static CompletionQueueSafeHandle GetCompletionQueue()
+ {
return GrpcEnvironment.ThreadPool.CompletionQueue;
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs
index 83d965debf..3a42dac1d7 100644
--- a/src/csharp/Grpc.Core/Channel.cs
+++ b/src/csharp/Grpc.Core/Channel.cs
@@ -36,10 +36,13 @@ using Grpc.Core.Internal;
namespace Grpc.Core
{
+ /// <summary>
+ /// gRPC Channel
+ /// </summary>
public class Channel : IDisposable
{
readonly ChannelSafeHandle handle;
- readonly String target;
+ readonly string target;
/// <summary>
/// Creates a channel.
diff --git a/src/csharp/Grpc.Core/ChannelArgs.cs b/src/csharp/Grpc.Core/ChannelArgs.cs
index 298b6edf20..74ab310e44 100644
--- a/src/csharp/Grpc.Core/ChannelArgs.cs
+++ b/src/csharp/Grpc.Core/ChannelArgs.cs
@@ -30,6 +30,7 @@
#endregion
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
@@ -37,33 +38,18 @@ using Grpc.Core.Internal;
namespace Grpc.Core
{
- // TODO: should we be using the builder pattern?
+ /// <summary>
+ /// gRPC channel options.
+ /// </summary>
public class ChannelArgs
{
public const string SslTargetNameOverrideKey = "grpc.ssl_target_name_override";
- public class Builder
- {
- Dictionary<string,string> stringArgs = new Dictionary<string,string>();
- // TODO: AddInteger not supported yet.
- public Builder AddString(string key, string value)
- {
- stringArgs.Add(key, value);
- return this;
- }
+ readonly ImmutableDictionary<string, string> stringArgs;
- public ChannelArgs Build()
- {
- return new ChannelArgs(stringArgs);
- }
- }
-
- Dictionary<string,string> stringArgs;
-
- private ChannelArgs(Dictionary<string, string> stringArgs)
+ private ChannelArgs(ImmutableDictionary<string, string> stringArgs)
{
- // TODO: use immutable dict?
- this.stringArgs = new Dictionary<string, string>(stringArgs);
+ this.stringArgs = stringArgs;
}
public string GetSslTargetNameOverride()
@@ -76,11 +62,28 @@ namespace Grpc.Core
return null;
}
- public static Builder NewBuilder()
+ public static Builder CreateBuilder()
{
return new Builder();
}
+ public class Builder
+ {
+ readonly Dictionary<string, string> stringArgs = new Dictionary<string, string>();
+
+ // TODO: AddInteger not supported yet.
+ public Builder AddString(string key, string value)
+ {
+ stringArgs.Add(key, value);
+ return this;
+ }
+
+ public ChannelArgs Build()
+ {
+ return new ChannelArgs(stringArgs.ToImmutableDictionary());
+ }
+ }
+
/// <summary>
/// Creates native object for the channel arguments.
/// </summary>
diff --git a/src/csharp/Grpc.Core/ClientStreamingAsyncResult.cs b/src/csharp/Grpc.Core/ClientStreamingAsyncResult.cs
index 44580a1154..65bedb0a33 100644
--- a/src/csharp/Grpc.Core/ClientStreamingAsyncResult.cs
+++ b/src/csharp/Grpc.Core/ClientStreamingAsyncResult.cs
@@ -67,4 +67,3 @@ namespace Grpc.Core
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Credentials.cs b/src/csharp/Grpc.Core/Credentials.cs
index 5116c277f7..15dd3ef321 100644
--- a/src/csharp/Grpc.Core/Credentials.cs
+++ b/src/csharp/Grpc.Core/Credentials.cs
@@ -36,6 +36,9 @@ using Grpc.Core.Internal;
namespace Grpc.Core
{
+ /// <summary>
+ /// Client-side credentials.
+ /// </summary>
public abstract class Credentials
{
/// <summary>
@@ -74,4 +77,3 @@ namespace Grpc.Core
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 78b6cdde59..78ba32b277 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -31,6 +31,9 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
+ <Reference Include="System.Collections.Immutable">
+ <HintPath>..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Internal\GrpcLog.cs" />
@@ -54,7 +57,7 @@
<Compile Include="Internal\ServerSafeHandle.cs" />
<Compile Include="Method.cs" />
<Compile Include="ServerCalls.cs" />
- <Compile Include="ServerCallHandler.cs" />
+ <Compile Include="Internal\ServerCallHandler.cs" />
<Compile Include="Marshaller.cs" />
<Compile Include="ServerServiceDefinition.cs" />
<Compile Include="Utils\RecordingObserver.cs" />
@@ -74,6 +77,15 @@
<Compile Include="OperationFailedException.cs" />
<Compile Include="Internal\AsyncCall.cs" />
<Compile Include="Utils\Preconditions.cs" />
+ <Compile Include="Internal\ServerCredentialsSafeHandle.cs" />
+ <Compile Include="ServerCredentials.cs" />
+ <Compile Include="Metadata.cs" />
+ <Compile Include="Internal\MetadataArraySafeHandle.cs" />
+ <Compile Include="Stub\AbstractStub.cs" />
+ <Compile Include="Stub\StubConfiguration.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
</ItemGroup>
<Choose>
<!-- Under older versions of Monodevelop, Choose is not supported and is just
@@ -88,4 +100,7 @@
<Otherwise />
</Choose>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <ItemGroup>
+ <Folder Include="Stub\" />
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs
index d3a8da4729..9c10a42e23 100644
--- a/src/csharp/Grpc.Core/GrpcEnvironment.cs
+++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs
@@ -63,8 +63,9 @@ namespace Grpc.Core
/// lifetime (and call Shutdown once you're done), for the sake of easier testing it's
/// allowed to initialize the environment again after it has been successfully shutdown.
/// </summary>
- public static void Initialize() {
- lock(staticLock)
+ public static void Initialize()
+ {
+ lock (staticLock)
{
if (instance == null)
{
@@ -79,7 +80,7 @@ namespace Grpc.Core
/// </summary>
public static void Shutdown()
{
- lock(staticLock)
+ lock (staticLock)
{
if (instance != null)
{
@@ -133,4 +134,3 @@ namespace Grpc.Core
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index 5ae036298b..bc72cb78de 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -54,7 +54,7 @@ namespace Grpc.Core.Internal
TaskCompletionSource<TResponse> unaryResponseTcs;
// Set after status is received. Only used for streaming response calls.
- Nullable<Status> finishedStatus;
+ Status? finishedStatus;
bool readObserverCompleted; // True if readObserver has already been completed.
@@ -64,7 +64,7 @@ namespace Grpc.Core.Internal
this.finishedHandler = CreateBatchCompletionCallback(HandleFinished);
}
- public void Initialize(Channel channel, CompletionQueueSafeHandle cq, String methodName)
+ public void Initialize(Channel channel, CompletionQueueSafeHandle cq, string methodName)
{
var call = CallSafeHandle.Create(channel.Handle, cq, methodName, channel.Target, Timespec.InfFuture);
InitializeInternal(call);
@@ -77,9 +77,9 @@ namespace Grpc.Core.Internal
/// <summary>
/// Blocking unary request - unary response call.
/// </summary>
- public TResponse UnaryCall(Channel channel, String methodName, TRequest msg)
+ public TResponse UnaryCall(Channel channel, string methodName, TRequest msg, Metadata headers)
{
- using(CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create())
+ using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create())
{
byte[] payload = UnsafeSerialize(msg);
@@ -92,7 +92,11 @@ namespace Grpc.Core.Internal
halfcloseRequested = true;
readingDone = true;
}
- call.BlockingUnary(cq, payload, unaryResponseHandler);
+
+ using (var metadataArray = MetadataArraySafeHandle.Create(headers))
+ {
+ call.BlockingUnary(cq, payload, unaryResponseHandler, metadataArray);
+ }
try
{
@@ -109,7 +113,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Starts a unary request - unary response call.
/// </summary>
- public Task<TResponse> UnaryCallAsync(TRequest msg)
+ public Task<TResponse> UnaryCallAsync(TRequest msg, Metadata headers)
{
lock (myLock)
{
@@ -122,8 +126,10 @@ namespace Grpc.Core.Internal
byte[] payload = UnsafeSerialize(msg);
unaryResponseTcs = new TaskCompletionSource<TResponse>();
- call.StartUnary(payload, unaryResponseHandler);
-
+ using (var metadataArray = MetadataArraySafeHandle.Create(headers))
+ {
+ call.StartUnary(payload, unaryResponseHandler, metadataArray);
+ }
return unaryResponseTcs.Task;
}
}
@@ -132,7 +138,7 @@ namespace Grpc.Core.Internal
/// Starts a streamed request - unary response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary>
- public Task<TResponse> ClientStreamingCallAsync()
+ public Task<TResponse> ClientStreamingCallAsync(Metadata headers)
{
lock (myLock)
{
@@ -142,7 +148,10 @@ namespace Grpc.Core.Internal
readingDone = true;
unaryResponseTcs = new TaskCompletionSource<TResponse>();
- call.StartClientStreaming(unaryResponseHandler);
+ using (var metadataArray = MetadataArraySafeHandle.Create(headers))
+ {
+ call.StartClientStreaming(unaryResponseHandler, metadataArray);
+ }
return unaryResponseTcs.Task;
}
@@ -151,7 +160,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Starts a unary request - streamed response call.
/// </summary>
- public void StartServerStreamingCall(TRequest msg, IObserver<TResponse> readObserver)
+ public void StartServerStreamingCall(TRequest msg, IObserver<TResponse> readObserver, Metadata headers)
{
lock (myLock)
{
@@ -165,7 +174,10 @@ namespace Grpc.Core.Internal
byte[] payload = UnsafeSerialize(msg);
- call.StartServerStreaming(payload, finishedHandler);
+ using (var metadataArray = MetadataArraySafeHandle.Create(headers))
+ {
+ call.StartServerStreaming(payload, finishedHandler, metadataArray);
+ }
StartReceiveMessage();
}
@@ -175,7 +187,7 @@ namespace Grpc.Core.Internal
/// Starts a streaming request - streaming response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary>
- public void StartDuplexStreamingCall(IObserver<TResponse> readObserver)
+ public void StartDuplexStreamingCall(IObserver<TResponse> readObserver, Metadata headers)
{
lock (myLock)
{
@@ -185,7 +197,10 @@ namespace Grpc.Core.Internal
this.readObserver = readObserver;
- call.StartDuplexStreaming(finishedHandler);
+ using (var metadataArray = MetadataArraySafeHandle.Create(headers))
+ {
+ call.StartDuplexStreaming(finishedHandler, metadataArray);
+ }
StartReceiveMessage();
}
@@ -254,7 +269,7 @@ namespace Grpc.Core.Internal
/// </summary>
private void HandleUnaryResponse(bool wasError, BatchContextSafeHandleNotOwned ctx)
{
- lock(myLock)
+ lock (myLock)
{
finished = true;
halfclosed = true;
@@ -264,9 +279,7 @@ namespace Grpc.Core.Internal
if (wasError)
{
- unaryResponseTcs.SetException(new RpcException(
- new Status(StatusCode.Internal, "Internal error occured.")
- ));
+ unaryResponseTcs.SetException(new RpcException(new Status(StatusCode.Internal, "Internal error occured.")));
return;
}
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
index 44d66b394c..15b0cfe249 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
@@ -225,7 +225,7 @@ namespace Grpc.Core.Internal
payload = serializer(msg);
return true;
}
- catch(Exception)
+ catch (Exception)
{
Console.WriteLine("Exception occured while trying to serialize message");
payload = null;
@@ -240,7 +240,7 @@ namespace Grpc.Core.Internal
msg = deserializer(payload);
return true;
}
- catch(Exception)
+ catch (Exception)
{
Console.WriteLine("Exception occured while trying to deserialize message");
msg = default(TRead);
@@ -254,7 +254,7 @@ namespace Grpc.Core.Internal
{
readObserver.OnNext(value);
}
- catch(Exception e)
+ catch (Exception e)
{
Console.WriteLine("Exception occured while invoking readObserver.OnNext: " + e);
}
@@ -266,7 +266,7 @@ namespace Grpc.Core.Internal
{
readObserver.OnCompleted();
}
- catch(Exception e)
+ catch (Exception e)
{
Console.WriteLine("Exception occured while invoking readObserver.OnCompleted: " + e);
}
@@ -278,7 +278,7 @@ namespace Grpc.Core.Internal
{
readObserver.OnError(error);
}
- catch(Exception e)
+ catch (Exception e)
{
Console.WriteLine("Exception occured while invoking readObserver.OnError: " + e);
}
@@ -290,7 +290,7 @@ namespace Grpc.Core.Internal
{
completionDelegate(error);
}
- catch(Exception e)
+ catch (Exception e)
{
Console.WriteLine("Exception occured while invoking completion delegate: " + e);
}
@@ -302,14 +302,15 @@ namespace Grpc.Core.Internal
/// </summary>
protected CompletionCallbackDelegate CreateBatchCompletionCallback(Action<bool, BatchContextSafeHandleNotOwned> handler)
{
- return new CompletionCallbackDelegate( (error, batchContextPtr) => {
+ return new CompletionCallbackDelegate((error, batchContextPtr) =>
+ {
try
{
var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr);
bool wasError = (error != GRPCOpError.GRPC_OP_OK);
handler(wasError, ctx);
}
- catch(Exception e)
+ catch (Exception e)
{
Console.WriteLine("Caught exception in a native handler: " + e);
}
@@ -363,7 +364,6 @@ namespace Grpc.Core.Internal
{
FireCompletion(origCompletionDelegate, null);
}
-
}
/// <summary>
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs b/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
index b78bb497fa..673b527fb2 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
@@ -91,5 +91,4 @@ namespace Grpc.Core.Internal
tcs.SetException(error);
}
}
-
} \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandleNotOwned.cs b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandleNotOwned.cs
index 75cd30e1a2..3c54753756 100644
--- a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandleNotOwned.cs
+++ b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandleNotOwned.cs
@@ -80,16 +80,18 @@ namespace Grpc.Core.Internal
{
return null;
}
- byte[] data = new byte[(int) len];
+ byte[] data = new byte[(int)len];
grpcsharp_batch_context_recv_message_to_buffer(this, data, new UIntPtr((ulong)data.Length));
return data;
}
- public CallSafeHandle GetServerRpcNewCall() {
+ public CallSafeHandle GetServerRpcNewCall()
+ {
return grpcsharp_batch_context_server_rpc_new_call(this);
}
- public string GetServerRpcNewMethod() {
+ public string GetServerRpcNewMethod()
+ {
return Marshal.PtrToStringAnsi(grpcsharp_batch_context_server_rpc_new_method(this));
}
}
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index 61566b5407..14add60c72 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -36,13 +36,14 @@ using Grpc.Core;
namespace Grpc.Core.Internal
{
- internal delegate void CompletionCallbackDelegate(GRPCOpError error,IntPtr batchContextPtr);
+ internal delegate void CompletionCallbackDelegate(GRPCOpError error, IntPtr batchContextPtr);
+
/// <summary>
/// grpc_call from <grpc/grpc.h>
/// </summary>
internal class CallSafeHandle : SafeHandleZeroIsInvalid
{
- const UInt32 GRPC_WRITE_BUFFER_HINT = 1;
+ const uint GRPC_WRITE_BUFFER_HINT = 1;
[DllImport("grpc_csharp_ext.dll")]
static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline);
@@ -56,25 +57,28 @@ namespace Grpc.Core.Internal
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_unary(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
- byte[] send_buffer, UIntPtr send_buffer_len);
+ byte[] send_buffer, UIntPtr send_buffer_len, MetadataArraySafeHandle metadataArray);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_call_blocking_unary(CallSafeHandle call, CompletionQueueSafeHandle dedicatedCq,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
- byte[] send_buffer, UIntPtr send_buffer_len);
+ byte[] send_buffer, UIntPtr send_buffer_len, MetadataArraySafeHandle metadataArray);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call,
- [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
+ [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
+ MetadataArraySafeHandle metadataArray);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_server_streaming(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
- byte[] send_buffer, UIntPtr send_buffer_len);
+ byte[] send_buffer, UIntPtr send_buffer_len,
+ MetadataArraySafeHandle metadataArray);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call,
- [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
+ [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
+ MetadataArraySafeHandle metadataArray);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_send_message(CallSafeHandle call,
@@ -108,29 +112,29 @@ namespace Grpc.Core.Internal
return grpcsharp_channel_create_call(channel, cq, method, host, deadline);
}
- public void StartUnary(byte[] payload, CompletionCallbackDelegate callback)
+ public void StartUnary(byte[] payload, CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray)
{
- AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong)payload.Length)));
+ AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong)payload.Length), metadataArray));
}
- public void BlockingUnary(CompletionQueueSafeHandle dedicatedCq, byte[] payload, CompletionCallbackDelegate callback)
+ public void BlockingUnary(CompletionQueueSafeHandle dedicatedCq, byte[] payload, CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray)
{
- grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong)payload.Length));
+ grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong)payload.Length), metadataArray);
}
- public void StartClientStreaming(CompletionCallbackDelegate callback)
+ public void StartClientStreaming(CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray)
{
- AssertCallOk(grpcsharp_call_start_client_streaming(this, callback));
+ AssertCallOk(grpcsharp_call_start_client_streaming(this, callback, metadataArray));
}
- public void StartServerStreaming(byte[] payload, CompletionCallbackDelegate callback)
+ public void StartServerStreaming(byte[] payload, CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray)
{
- AssertCallOk(grpcsharp_call_start_server_streaming(this, callback, payload, new UIntPtr((ulong)payload.Length)));
+ AssertCallOk(grpcsharp_call_start_server_streaming(this, callback, payload, new UIntPtr((ulong)payload.Length), metadataArray));
}
- public void StartDuplexStreaming(CompletionCallbackDelegate callback)
+ public void StartDuplexStreaming(CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray)
{
- AssertCallOk(grpcsharp_call_start_duplex_streaming(this, callback));
+ AssertCallOk(grpcsharp_call_start_duplex_streaming(this, callback, metadataArray));
}
public void StartSendMessage(byte[] payload, CompletionCallbackDelegate callback)
@@ -179,7 +183,7 @@ namespace Grpc.Core.Internal
Trace.Assert(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK");
}
- private static UInt32 GetFlags(bool buffered)
+ private static uint GetFlags(bool buffered)
{
return buffered ? 0 : GRPC_WRITE_BUFFER_HINT;
}
diff --git a/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs
index ca3c21d84c..c69f1a0d02 100644
--- a/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs
@@ -74,4 +74,3 @@ namespace Grpc.Core.Internal
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
index 6bff923c55..600d1fc87c 100644
--- a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
@@ -77,4 +77,3 @@ namespace Grpc.Core.Internal
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Internal/Enums.cs b/src/csharp/Grpc.Core/Internal/Enums.cs
index f363050b07..94a2fd1784 100644
--- a/src/csharp/Grpc.Core/Internal/Enums.cs
+++ b/src/csharp/Grpc.Core/Internal/Enums.cs
@@ -112,4 +112,3 @@ namespace Grpc.Core.Internal
GRPC_OP_ERROR
}
}
-
diff --git a/src/csharp/Grpc.Core/Internal/GrpcLog.cs b/src/csharp/Grpc.Core/Internal/GrpcLog.cs
index 98768d05c6..2f3c8ad71c 100644
--- a/src/csharp/Grpc.Core/Internal/GrpcLog.cs
+++ b/src/csharp/Grpc.Core/Internal/GrpcLog.cs
@@ -40,7 +40,7 @@ using System.Threading;
namespace Grpc.Core.Internal
{
- internal delegate void GprLogDelegate(IntPtr fileStringPtr, Int32 line, UInt64 threadId, IntPtr severityStringPtr, IntPtr msgPtr);
+ internal delegate void GprLogDelegate(IntPtr fileStringPtr, int line, ulong threadId, IntPtr severityStringPtr, IntPtr msgPtr);
/// <summary>
/// Logs from gRPC C core library can get lost if your application is not a console app.
@@ -73,7 +73,7 @@ namespace Grpc.Core.Internal
}
}
- private static void HandleWrite(IntPtr fileStringPtr, Int32 line, UInt64 threadId, IntPtr severityStringPtr, IntPtr msgPtr)
+ private static void HandleWrite(IntPtr fileStringPtr, int line, ulong threadId, IntPtr severityStringPtr, IntPtr msgPtr)
{
try
{
diff --git a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
index 9e69fe2f43..f4224668f1 100644
--- a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
+++ b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
@@ -51,12 +51,13 @@ namespace Grpc.Core.Internal
CompletionQueueSafeHandle cq;
- public GrpcThreadPool(int poolSize) {
+ public GrpcThreadPool(int poolSize)
+ {
this.poolSize = poolSize;
}
- public void Start() {
-
+ public void Start()
+ {
lock (myLock)
{
if (cq != null)
@@ -73,8 +74,8 @@ namespace Grpc.Core.Internal
}
}
- public void Stop() {
-
+ public void Stop()
+ {
lock (myLock)
{
cq.Shutdown();
@@ -86,7 +87,6 @@ namespace Grpc.Core.Internal
}
cq.Dispose();
-
}
}
@@ -116,10 +116,9 @@ namespace Grpc.Core.Internal
do
{
completionType = cq.NextWithCallback();
- } while(completionType != GRPCCompletionType.GRPC_QUEUE_SHUTDOWN);
+ }
+ while (completionType != GRPCCompletionType.GRPC_QUEUE_SHUTDOWN);
Console.WriteLine("Completion queue has shutdown successfully, thread " + Thread.CurrentThread.Name + " exiting.");
}
}
-
}
-
diff --git a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
new file mode 100644
index 0000000000..c9c4d954c9
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
@@ -0,0 +1,72 @@
+#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.Runtime.InteropServices;
+using System.Threading.Tasks;
+
+namespace Grpc.Core.Internal
+{
+ /// <summary>
+ /// grpc_metadata_array from <grpc/grpc.h>
+ /// </summary>
+ internal class MetadataArraySafeHandle : SafeHandleZeroIsInvalid
+ {
+ [DllImport("grpc_csharp_ext.dll")]
+ static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity);
+
+ [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
+ static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength);
+
+ [DllImport("grpc_csharp_ext.dll")]
+ static extern void grpcsharp_metadata_array_destroy_full(IntPtr array);
+
+ private MetadataArraySafeHandle()
+ {
+ }
+
+ public static MetadataArraySafeHandle Create(Metadata metadata)
+ {
+ var entries = metadata.Entries;
+ var metadataArray = grpcsharp_metadata_array_create(new UIntPtr((ulong)entries.Count));
+ for (int i = 0; i < entries.Count; i++)
+ {
+ grpcsharp_metadata_array_add(metadataArray, entries[i].Key, entries[i].ValueBytes, new UIntPtr((ulong)entries[i].ValueBytes.Length));
+ }
+ return metadataArray;
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ grpcsharp_metadata_array_destroy_full(handle);
+ return true;
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs b/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs
index aa6fce2e96..702aea2883 100644
--- a/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs
+++ b/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs
@@ -64,4 +64,3 @@ namespace Grpc.Core.Internal
}
}
}
-
diff --git a/src/csharp/Grpc.Core/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
index 3eb8422f57..25fd4fab8f 100644
--- a/src/csharp/Grpc.Core/ServerCallHandler.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
@@ -36,7 +36,7 @@ using System.Linq;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
-namespace Grpc.Core
+namespace Grpc.Core.Internal
{
internal interface IServerCallHandler
{
@@ -70,7 +70,6 @@ namespace Grpc.Core
handler(request, responseObserver);
finishedTask.Wait();
-
}
}
@@ -93,7 +92,7 @@ namespace Grpc.Core
asyncCall.Initialize(call);
- var responseObserver = new ServerStreamingOutputObserver<TRequest,TResponse>(asyncCall);
+ var responseObserver = new ServerStreamingOutputObserver<TRequest, TResponse>(asyncCall);
var requestObserver = handler(responseObserver);
var finishedTask = asyncCall.ServerSideCallAsync(requestObserver);
finishedTask.Wait();
@@ -113,7 +112,7 @@ namespace Grpc.Core
var finishedTask = asyncCall.ServerSideCallAsync(new NullObserver<byte[]>());
// TODO: check result of the completion status.
- asyncCall.StartSendStatusFromServer(new Status(StatusCode.Unimplemented, "No such method."), new AsyncCompletionDelegate((error) => {}));
+ asyncCall.StartSendStatusFromServer(new Status(StatusCode.Unimplemented, "No such method."), new AsyncCompletionDelegate((error) => { }));
finishedTask.Wait();
}
@@ -132,7 +131,5 @@ namespace Grpc.Core
public void OnNext(T value)
{
}
-
}
}
-
diff --git a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
new file mode 100644
index 0000000000..961180741a
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
@@ -0,0 +1,68 @@
+#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.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core.Internal
+{
+ /// <summary>
+ /// grpc_server_credentials from <grpc/grpc_security.h>
+ /// </summary>
+ internal class ServerCredentialsSafeHandle : SafeHandleZeroIsInvalid
+ {
+ [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
+ static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs);
+
+ [DllImport("grpc_csharp_ext.dll")]
+ static extern void grpcsharp_server_credentials_release(IntPtr credentials);
+
+ private ServerCredentialsSafeHandle()
+ {
+ }
+
+ public static ServerCredentialsSafeHandle CreateSslCredentials(string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray)
+ {
+ Preconditions.CheckArgument(keyCertPairCertChainArray.Length == keyCertPairPrivateKeyArray.Length);
+ return grpcsharp_ssl_server_credentials_create(null,
+ keyCertPairCertChainArray, keyCertPairPrivateKeyArray,
+ new UIntPtr((ulong)keyCertPairCertChainArray.Length));
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ grpcsharp_server_credentials_release(handle);
+ return true;
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
index de9bbaf7c1..a59da09822 100644
--- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
@@ -53,7 +53,10 @@ namespace Grpc.Core.Internal
static extern ServerSafeHandle grpcsharp_server_create(CompletionQueueSafeHandle cq, IntPtr args);
[DllImport("grpc_csharp_ext.dll")]
- static extern Int32 grpcsharp_server_add_http2_port(ServerSafeHandle server, string addr);
+ static extern int grpcsharp_server_add_http2_port(ServerSafeHandle server, string addr);
+
+ [DllImport("grpc_csharp_ext.dll")]
+ static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_server_start(ServerSafeHandle server);
@@ -74,15 +77,19 @@ namespace Grpc.Core.Internal
public static ServerSafeHandle NewServer(CompletionQueueSafeHandle cq, IntPtr args)
{
- // TODO: also grpc_secure_server_create...
return grpcsharp_server_create(cq, args);
}
- public int AddPort(string addr)
+ public int AddListeningPort(string addr)
{
return grpcsharp_server_add_http2_port(this, addr);
}
+ public int AddListeningPort(string addr, ServerCredentialsSafeHandle credentials)
+ {
+ return grpcsharp_server_add_secure_http2_port(this, addr, credentials);
+ }
+
public void Start()
{
grpcsharp_server_start(this);
diff --git a/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs b/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs
index 9873dc9c71..97b62d0569 100644
--- a/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs
@@ -69,4 +69,3 @@ namespace Grpc.Core.Internal
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Internal/Timespec.cs b/src/csharp/Grpc.Core/Internal/Timespec.cs
index e6efd66f13..94d48c2c49 100644
--- a/src/csharp/Grpc.Core/Internal/Timespec.cs
+++ b/src/csharp/Grpc.Core/Internal/Timespec.cs
@@ -40,8 +40,8 @@ namespace Grpc.Core.Internal
[StructLayout(LayoutKind.Sequential)]
internal struct Timespec
{
- const int nanosPerSecond = 1000 * 1000 * 1000;
- const int nanosPerTick = 100;
+ const int NanosPerSecond = 1000 * 1000 * 1000;
+ const int NanosPerTick = 100;
[DllImport("grpc_csharp_ext.dll")]
static extern Timespec gprsharp_now();
@@ -99,14 +99,13 @@ namespace Grpc.Core.Internal
public Timespec Add(TimeSpan timeSpan)
{
- long nanos = tv_nsec.ToInt64() + (timeSpan.Ticks % TimeSpan.TicksPerSecond) * nanosPerTick;
- long overflow_sec = (nanos > nanosPerSecond) ? 1 : 0;
+ long nanos = tv_nsec.ToInt64() + (timeSpan.Ticks % TimeSpan.TicksPerSecond) * NanosPerTick;
+ long overflow_sec = (nanos > NanosPerSecond) ? 1 : 0;
Timespec result;
- result.tv_nsec = new IntPtr(nanos % nanosPerSecond);
+ result.tv_nsec = new IntPtr(nanos % NanosPerSecond);
result.tv_sec = new IntPtr(tv_sec.ToInt64() + (timeSpan.Ticks / TimeSpan.TicksPerSecond) + overflow_sec);
return result;
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core/Marshaller.cs
index 602e0eb824..8b1a929074 100644
--- a/src/csharp/Grpc.Core/Marshaller.cs
+++ b/src/csharp/Grpc.Core/Marshaller.cs
@@ -32,6 +32,7 @@
#endregion
using System;
+using Grpc.Core.Utils;
namespace Grpc.Core
{
@@ -40,13 +41,13 @@ namespace Grpc.Core
/// </summary>
public struct Marshaller<T>
{
- readonly Func<T,byte[]> serializer;
- readonly Func<byte[],T> deserializer;
+ readonly Func<T, byte[]> serializer;
+ readonly Func<byte[], T> deserializer;
public Marshaller(Func<T, byte[]> serializer, Func<byte[], T> deserializer)
{
- this.serializer = serializer;
- this.deserializer = deserializer;
+ this.serializer = Preconditions.CheckNotNull(serializer);
+ this.deserializer = Preconditions.CheckNotNull(deserializer);
}
public Func<T, byte[]> Serializer
@@ -66,9 +67,12 @@ namespace Grpc.Core
}
}
- public static class Marshallers {
-
- public static Marshaller<T> Create<T>(Func<T,byte[]> serializer, Func<byte[],T> deserializer)
+ /// <summary>
+ /// Utilities for creating marshallers.
+ /// </summary>
+ public static class Marshallers
+ {
+ public static Marshaller<T> Create<T>(Func<T, byte[]> serializer, Func<byte[], T> deserializer)
{
return new Marshaller<T>(serializer, deserializer);
}
@@ -81,7 +85,5 @@ namespace Grpc.Core
System.Text.Encoding.UTF8.GetString);
}
}
-
}
}
-
diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core/Metadata.cs
new file mode 100644
index 0000000000..eccec26a61
--- /dev/null
+++ b/src/csharp/Grpc.Core/Metadata.cs
@@ -0,0 +1,126 @@
+#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.Collections.Immutable;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Grpc.Core
+{
+ /// <summary>
+ /// gRPC call metadata.
+ /// </summary>
+ public class Metadata
+ {
+ public static readonly Metadata Empty = new Metadata(ImmutableList<MetadataEntry>.Empty);
+
+ readonly ImmutableList<MetadataEntry> entries;
+
+ public Metadata(ImmutableList<MetadataEntry> entries)
+ {
+ this.entries = entries;
+ }
+
+ public ImmutableList<MetadataEntry> Entries
+ {
+ get
+ {
+ return this.entries;
+ }
+ }
+
+ public static Builder CreateBuilder()
+ {
+ return new Builder();
+ }
+
+ public struct MetadataEntry
+ {
+ readonly string key;
+ readonly byte[] valueBytes;
+
+ public MetadataEntry(string key, byte[] valueBytes)
+ {
+ this.key = key;
+ this.valueBytes = valueBytes;
+ }
+
+ public MetadataEntry(string key, string value)
+ {
+ this.key = key;
+ this.valueBytes = Encoding.ASCII.GetBytes(value);
+ }
+
+ public string Key
+ {
+ get
+ {
+ return this.key;
+ }
+ }
+
+ // TODO: using ByteString would guarantee immutability.
+ public byte[] ValueBytes
+ {
+ get
+ {
+ return this.valueBytes;
+ }
+ }
+ }
+
+ public class Builder
+ {
+ readonly List<Metadata.MetadataEntry> entries = new List<Metadata.MetadataEntry>();
+
+ public List<MetadataEntry> Entries
+ {
+ get
+ {
+ return entries;
+ }
+ }
+
+ public Builder Add(MetadataEntry entry)
+ {
+ entries.Add(entry);
+ return this;
+ }
+
+ public Metadata Build()
+ {
+ return new Metadata(entries.ToImmutableList());
+ }
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/Method.cs b/src/csharp/Grpc.Core/Method.cs
index c94aa8161f..4f97eeef37 100644
--- a/src/csharp/Grpc.Core/Method.cs
+++ b/src/csharp/Grpc.Core/Method.cs
@@ -94,4 +94,3 @@ namespace Grpc.Core
}
}
}
-
diff --git a/src/csharp/Grpc.Core/OperationFailedException.cs b/src/csharp/Grpc.Core/OperationFailedException.cs
index 34a8c95a85..9b1c24d0c1 100644
--- a/src/csharp/Grpc.Core/OperationFailedException.cs
+++ b/src/csharp/Grpc.Core/OperationFailedException.cs
@@ -45,4 +45,3 @@ namespace Grpc.Core
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
index 37ba1e2263..168939cf8c 100644
--- a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
@@ -1,24 +1,14 @@
using System.Reflection;
using System.Runtime.CompilerServices;
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
-[assembly: AssemblyTitle ("Grpc.Core")]
-[assembly: AssemblyDescription ("")]
-[assembly: AssemblyConfiguration ("")]
-[assembly: AssemblyCompany ("")]
-[assembly: AssemblyProduct ("")]
-[assembly: AssemblyCopyright ("Google Inc. All rights reserved.")]
-[assembly: AssemblyTrademark ("")]
-[assembly: AssemblyCulture ("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-[assembly: AssemblyVersion ("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyTitle("Grpc.Core")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("0.1.*")]
[assembly: InternalsVisibleTo("Grpc.Core.Tests")]
-
diff --git a/src/csharp/Grpc.Core/RpcException.cs b/src/csharp/Grpc.Core/RpcException.cs
index e1cf64ca56..433d87215e 100644
--- a/src/csharp/Grpc.Core/RpcException.cs
+++ b/src/csharp/Grpc.Core/RpcException.cs
@@ -35,6 +35,9 @@ using System;
namespace Grpc.Core
{
+ /// <summary>
+ /// Thrown when remote procedure call fails.
+ /// </summary>
public class RpcException : Exception
{
private readonly Status status;
@@ -58,4 +61,3 @@ namespace Grpc.Core
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index 152cc2176c..f086fa8beb 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -67,16 +67,27 @@ namespace Grpc.Core
}
// only call this before Start()
- public void AddServiceDefinition(ServerServiceDefinition serviceDefinition) {
- foreach(var entry in serviceDefinition.CallHandlers)
+ public void AddServiceDefinition(ServerServiceDefinition serviceDefinition)
+ {
+ foreach (var entry in serviceDefinition.CallHandlers)
{
callHandlers.Add(entry.Key, entry.Value);
}
}
// only call before Start()
- public int AddPort(string addr) {
- return handle.AddPort(addr);
+ public int AddListeningPort(string addr)
+ {
+ return handle.AddListeningPort(addr);
+ }
+
+ // only call before Start()
+ public int AddListeningPort(string addr, ServerCredentials credentials)
+ {
+ using (var nativeCredentials = credentials.ToNativeCredentials())
+ {
+ return handle.AddListeningPort(addr, nativeCredentials);
+ }
}
public void Start()
@@ -98,7 +109,7 @@ namespace Grpc.Core
{
var rpcInfo = newRpcQueue.Take();
- //Console.WriteLine("Server received RPC " + rpcInfo.Method);
+ // Console.WriteLine("Server received RPC " + rpcInfo.Method);
IServerCallHandler callHandler;
if (!callHandlers.TryGetValue(rpcInfo.Method, out callHandler))
@@ -107,7 +118,7 @@ namespace Grpc.Core
}
callHandler.StartCall(rpcInfo.Method, rpcInfo.Call, GetCompletionQueue());
}
- catch(Exception e)
+ catch (Exception e)
{
Console.WriteLine("Exception while handling RPC: " + e);
}
@@ -118,7 +129,8 @@ namespace Grpc.Core
/// cleans up used resources.
/// </summary>
/// <returns>The async.</returns>
- public async Task ShutdownAsync() {
+ public async Task ShutdownAsync()
+ {
handle.ShutdownAndNotify(serverShutdownHandler);
await shutdownTcs.Task;
handle.Dispose();
@@ -135,11 +147,13 @@ namespace Grpc.Core
}
}
- public void Kill() {
+ public void Kill()
+ {
handle.Dispose();
}
- private async Task StartHandlingRpcs() {
+ private async Task StartHandlingRpcs()
+ {
while (true)
{
await Task.Factory.StartNew(RunRpc);
@@ -151,22 +165,27 @@ namespace Grpc.Core
AssertCallOk(handle.RequestCall(GetCompletionQueue(), newServerRpcHandler));
}
- private void HandleNewServerRpc(GRPCOpError error, IntPtr batchContextPtr) {
- try {
+ private void HandleNewServerRpc(GRPCOpError error, IntPtr batchContextPtr)
+ {
+ try
+ {
var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr);
- if (error != GRPCOpError.GRPC_OP_OK) {
+ if (error != GRPCOpError.GRPC_OP_OK)
+ {
// TODO: handle error
}
var rpcInfo = new NewRpcInfo(ctx.GetServerRpcNewCall(), ctx.GetServerRpcNewMethod());
// after server shutdown, the callback returns with null call
- if (!rpcInfo.Call.IsInvalid) {
+ if (!rpcInfo.Call.IsInvalid)
+ {
newRpcQueue.Add(rpcInfo);
}
-
- } catch(Exception e) {
+ }
+ catch (Exception e)
+ {
Console.WriteLine("Caught exception in a native handler: " + e);
}
}
diff --git a/src/csharp/Grpc.Core/ServerCalls.cs b/src/csharp/Grpc.Core/ServerCalls.cs
index bed77796de..dcae99446f 100644
--- a/src/csharp/Grpc.Core/ServerCalls.cs
+++ b/src/csharp/Grpc.Core/ServerCalls.cs
@@ -32,17 +32,18 @@
#endregion
using System;
+using Grpc.Core.Internal;
namespace Grpc.Core
{
// TODO: perhaps add also serverSideStreaming and clientSideStreaming
- public delegate void UnaryRequestServerMethod<TRequest, TResponse> (TRequest request, IObserver<TResponse> responseObserver);
+ public delegate void UnaryRequestServerMethod<TRequest, TResponse>(TRequest request, IObserver<TResponse> responseObserver);
- public delegate IObserver<TRequest> StreamingRequestServerMethod<TRequest, TResponse> (IObserver<TResponse> responseObserver);
-
- internal static class ServerCalls {
+ public delegate IObserver<TRequest> StreamingRequestServerMethod<TRequest, TResponse>(IObserver<TResponse> responseObserver);
+ internal static class ServerCalls
+ {
public static IServerCallHandler UnaryRequestCall<TRequest, TResponse>(Method<TRequest, TResponse> method, UnaryRequestServerMethod<TRequest, TResponse> handler)
{
return new UnaryRequestServerCallHandler<TRequest, TResponse>(method, handler);
@@ -52,7 +53,5 @@ namespace Grpc.Core
{
return new StreamingRequestServerCallHandler<TRequest, TResponse>(method, handler);
}
-
}
}
-
diff --git a/src/csharp/Grpc.Core/ServerCredentials.cs b/src/csharp/Grpc.Core/ServerCredentials.cs
new file mode 100644
index 0000000000..ab7d0b4914
--- /dev/null
+++ b/src/csharp/Grpc.Core/ServerCredentials.cs
@@ -0,0 +1,109 @@
+#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.Collections.Immutable;
+using Grpc.Core.Internal;
+
+namespace Grpc.Core
+{
+ /// <summary>
+ /// Server side credentials.
+ /// </summary>
+ public abstract class ServerCredentials
+ {
+ /// <summary>
+ /// Creates native object for the credentials.
+ /// </summary>
+ /// <returns>The native credentials.</returns>
+ internal abstract ServerCredentialsSafeHandle ToNativeCredentials();
+ }
+
+ /// <summary>
+ /// Key certificate pair (in PEM encoding).
+ /// </summary>
+ public class KeyCertificatePair
+ {
+ readonly string certChain;
+ readonly string privateKey;
+
+ public KeyCertificatePair(string certChain, string privateKey)
+ {
+ this.certChain = certChain;
+ this.privateKey = privateKey;
+ }
+
+ public string CertChain
+ {
+ get
+ {
+ return certChain;
+ }
+ }
+
+ public string PrivateKey
+ {
+ get
+ {
+ return privateKey;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Server-side SSL credentials.
+ /// </summary>
+ public class SslServerCredentials : ServerCredentials
+ {
+ ImmutableList<KeyCertificatePair> keyCertPairs;
+
+ public SslServerCredentials(ImmutableList<KeyCertificatePair> keyCertPairs)
+ {
+ this.keyCertPairs = keyCertPairs;
+ }
+
+ internal override ServerCredentialsSafeHandle ToNativeCredentials()
+ {
+ int count = keyCertPairs.Count;
+ string[] certChains = new string[count];
+ string[] keys = new string[count];
+ for (int i = 0; i < count; i++)
+ {
+ certChains[i] = keyCertPairs[i].CertChain;
+ keys[i] = keyCertPairs[i].PrivateKey;
+ }
+ return ServerCredentialsSafeHandle.CreateSslCredentials(certChains, keys);
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/ServerServiceDefinition.cs b/src/csharp/Grpc.Core/ServerServiceDefinition.cs
index 231c376062..f08c7d88f3 100644
--- a/src/csharp/Grpc.Core/ServerServiceDefinition.cs
+++ b/src/csharp/Grpc.Core/ServerServiceDefinition.cs
@@ -33,22 +33,24 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
+using Grpc.Core.Internal;
namespace Grpc.Core
{
+ /// <summary>
+ /// Mapping of method names to server call handlers.
+ /// </summary>
public class ServerServiceDefinition
{
- readonly string serviceName;
- // TODO: we would need an immutable dictionary here...
- readonly Dictionary<string, IServerCallHandler> callHandlers;
+ readonly ImmutableDictionary<string, IServerCallHandler> callHandlers;
- private ServerServiceDefinition(string serviceName, Dictionary<string, IServerCallHandler> callHandlers)
+ private ServerServiceDefinition(ImmutableDictionary<string, IServerCallHandler> callHandlers)
{
- this.serviceName = serviceName;
- this.callHandlers = new Dictionary<string, IServerCallHandler>(callHandlers);
+ this.callHandlers = callHandlers;
}
- internal Dictionary<string, IServerCallHandler> CallHandlers
+ internal ImmutableDictionary<string, IServerCallHandler> CallHandlers
{
get
{
@@ -56,8 +58,7 @@ namespace Grpc.Core
}
}
-
- public static Builder CreateBuilder(String serviceName)
+ public static Builder CreateBuilder(string serviceName)
{
return new Builder(serviceName);
}
@@ -65,7 +66,7 @@ namespace Grpc.Core
public class Builder
{
readonly string serviceName;
- readonly Dictionary<string, IServerCallHandler> callHandlers = new Dictionary<String, IServerCallHandler>();
+ readonly Dictionary<string, IServerCallHandler> callHandlers = new Dictionary<string, IServerCallHandler>();
public Builder(string serviceName)
{
@@ -76,7 +77,7 @@ namespace Grpc.Core
Method<TRequest, TResponse> method,
UnaryRequestServerMethod<TRequest, TResponse> handler)
{
- callHandlers.Add(method.Name, ServerCalls.UnaryRequestCall(method, handler));
+ callHandlers.Add(GetFullMethodName(serviceName, method.Name), ServerCalls.UnaryRequestCall(method, handler));
return this;
}
@@ -84,15 +85,19 @@ namespace Grpc.Core
Method<TRequest, TResponse> method,
StreamingRequestServerMethod<TRequest, TResponse> handler)
{
- callHandlers.Add(method.Name, ServerCalls.StreamingRequestCall(method, handler));
+ callHandlers.Add(GetFullMethodName(serviceName, method.Name), ServerCalls.StreamingRequestCall(method, handler));
return this;
}
public ServerServiceDefinition Build()
{
- return new ServerServiceDefinition(serviceName, callHandlers);
+ return new ServerServiceDefinition(callHandlers.ToImmutableDictionary());
+ }
+
+ private string GetFullMethodName(string serviceName, string methodName)
+ {
+ return serviceName + "/" + methodName;
}
}
}
}
-
diff --git a/src/csharp/Grpc.Core/StatusCode.cs b/src/csharp/Grpc.Core/StatusCode.cs
index 1987e52789..a9696fa469 100644
--- a/src/csharp/Grpc.Core/StatusCode.cs
+++ b/src/csharp/Grpc.Core/StatusCode.cs
@@ -35,9 +35,9 @@ using System;
namespace Grpc.Core
{
- // TODO: element names should changed to comply with C# naming conventions.
/// <summary>
- /// based on grpc_status_code from grpc/status.h
+ /// Result of a remote procedure call.
+ /// Based on grpc_status_code from grpc/status.h
/// </summary>
public enum StatusCode
{
@@ -139,4 +139,3 @@ namespace Grpc.Core
DataLoss = 15
}
}
-
diff --git a/src/csharp/Grpc.Core/Stub/AbstractStub.cs b/src/csharp/Grpc.Core/Stub/AbstractStub.cs
new file mode 100644
index 0000000000..cf5ab958c5
--- /dev/null
+++ b/src/csharp/Grpc.Core/Stub/AbstractStub.cs
@@ -0,0 +1,73 @@
+#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 Grpc.Core.Internal;
+
+namespace Grpc.Core
+{
+ // TODO: support adding timeout to methods.
+ /// <summary>
+ /// Base for client-side stubs.
+ /// </summary>
+ public abstract class AbstractStub<TStub, TConfig>
+ where TConfig : StubConfiguration
+ {
+ readonly Channel channel;
+ readonly TConfig config;
+
+ public AbstractStub(Channel channel, TConfig config)
+ {
+ this.channel = channel;
+ this.config = config;
+ }
+
+ public Channel Channel
+ {
+ get
+ {
+ return this.channel;
+ }
+ }
+
+ /// <summary>
+ /// Creates a new call to given method.
+ /// </summary>
+ protected Call<TRequest, TResponse> CreateCall<TRequest, TResponse>(string serviceName, Method<TRequest, TResponse> method)
+ {
+ var headerBuilder = Metadata.CreateBuilder();
+ config.HeaderInterceptor(headerBuilder);
+ return new Call<TRequest, TResponse>(serviceName, method, channel, headerBuilder.Build());
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/Stub/StubConfiguration.cs b/src/csharp/Grpc.Core/Stub/StubConfiguration.cs
new file mode 100644
index 0000000000..5bcb5b40d2
--- /dev/null
+++ b/src/csharp/Grpc.Core/Stub/StubConfiguration.cs
@@ -0,0 +1,64 @@
+#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 Grpc.Core.Internal;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core
+{
+ public delegate void HeaderInterceptorDelegate(Metadata.Builder headerBuilder);
+
+ public class StubConfiguration
+ {
+ /// <summary>
+ /// The default stub configuration.
+ /// </summary>
+ public static readonly StubConfiguration Default = new StubConfiguration((headerBuilder) => { });
+
+ readonly HeaderInterceptorDelegate headerInterceptor;
+
+ public StubConfiguration(HeaderInterceptorDelegate headerInterceptor)
+ {
+ this.headerInterceptor = Preconditions.CheckNotNull(headerInterceptor);
+ }
+
+ public HeaderInterceptorDelegate HeaderInterceptor
+ {
+ get
+ {
+ return headerInterceptor;
+ }
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs b/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs
index 3f0dae84cf..4180d98938 100644
--- a/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs
+++ b/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs
@@ -32,10 +32,10 @@
#endregion
using System;
-using System.Threading.Tasks;
-using System.Collections.Generic;
using System.Collections.Concurrent;
+using System.Collections.Generic;
using System.Diagnostics;
+using System.Threading.Tasks;
namespace Grpc.Core.Utils
{
@@ -61,8 +61,7 @@ namespace Grpc.Core.Utils
}
stopwatch.Stop();
Console.WriteLine("Elapsed time: " + stopwatch.ElapsedMilliseconds + "ms");
- Console.WriteLine("Ops per second: " + (int) ((double) benchmarkIterations * 1000 / stopwatch.ElapsedMilliseconds));
+ Console.WriteLine("Ops per second: " + (int)((double)benchmarkIterations * 1000 / stopwatch.ElapsedMilliseconds));
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs b/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs
index 18702e1cc4..c4d6bee058 100644
--- a/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs
+++ b/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs
@@ -42,7 +42,8 @@ namespace Grpc.Core.Utils
/// Otherwise, rethrows the original aggregate exception.
/// Always throws, the exception return type is here only to make the.
/// </summary>
- public static Exception UnwrapRpcException(AggregateException ae) {
+ public static Exception UnwrapRpcException(AggregateException ae)
+ {
foreach (var e in ae.InnerExceptions)
{
if (e is RpcException)
@@ -54,4 +55,3 @@ namespace Grpc.Core.Utils
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Utils/Preconditions.cs b/src/csharp/Grpc.Core/Utils/Preconditions.cs
index b17ce42117..aeb5d210a7 100644
--- a/src/csharp/Grpc.Core/Utils/Preconditions.cs
+++ b/src/csharp/Grpc.Core/Utils/Preconditions.cs
@@ -32,10 +32,10 @@
#endregion
using System;
-using System.Threading.Tasks;
-using System.Collections.Generic;
using System.Collections.Concurrent;
+using System.Collections.Generic;
using System.Diagnostics;
+using System.Threading.Tasks;
namespace Grpc.Core.Utils
{
@@ -66,7 +66,7 @@ namespace Grpc.Core.Utils
/// <summary>
/// Throws NullReferenceException if reference is null.
/// </summary>
- public static T CheckNotNull<T> (T reference)
+ public static T CheckNotNull<T>(T reference)
{
if (reference == null)
{
@@ -78,7 +78,7 @@ namespace Grpc.Core.Utils
/// <summary>
/// Throws NullReferenceException with given message if reference is null.
/// </summary>
- public static T CheckNotNull<T> (T reference, string errorMessage)
+ public static T CheckNotNull<T>(T reference, string errorMessage)
{
if (reference == null)
{
@@ -110,4 +110,3 @@ namespace Grpc.Core.Utils
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Utils/RecordingObserver.cs b/src/csharp/Grpc.Core/Utils/RecordingObserver.cs
index 99d2725b70..7b43ab8ad5 100644
--- a/src/csharp/Grpc.Core/Utils/RecordingObserver.cs
+++ b/src/csharp/Grpc.Core/Utils/RecordingObserver.cs
@@ -57,9 +57,9 @@ namespace Grpc.Core.Utils
data.Add(value);
}
- public Task<List<T>> ToList() {
+ public Task<List<T>> ToList()
+ {
return tcs.Task;
}
}
}
-
diff --git a/src/csharp/Grpc.Core/Utils/RecordingQueue.cs b/src/csharp/Grpc.Core/Utils/RecordingQueue.cs
index 63992da6a9..9749168af0 100644
--- a/src/csharp/Grpc.Core/Utils/RecordingQueue.cs
+++ b/src/csharp/Grpc.Core/Utils/RecordingQueue.cs
@@ -32,9 +32,9 @@
#endregion
using System;
-using System.Threading.Tasks;
-using System.Collections.Generic;
using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Threading.Tasks;
namespace Grpc.Core.Utils
{
@@ -81,4 +81,3 @@ namespace Grpc.Core.Utils
}
}
}
-
diff --git a/src/csharp/Grpc.Core/packages.config b/src/csharp/Grpc.Core/packages.config
new file mode 100644
index 0000000000..cf711ac362
--- /dev/null
+++ b/src/csharp/Grpc.Core/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="System.Collections.Immutable" version="1.1.34-rc" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs
index bdd7189db2..11fc099a95 100644
--- a/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs
@@ -1,22 +1,12 @@
using System.Reflection;
using System.Runtime.CompilerServices;
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
-[assembly: AssemblyTitle ("Grpc.Examples.MathClient")]
-[assembly: AssemblyDescription ("")]
-[assembly: AssemblyConfiguration ("")]
-[assembly: AssemblyCompany ("")]
-[assembly: AssemblyProduct ("")]
-[assembly: AssemblyCopyright ("Google Inc. All rights reserved.")]
-[assembly: AssemblyTrademark ("")]
-[assembly: AssemblyCulture ("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-[assembly: AssemblyVersion ("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
+[assembly: AssemblyTitle("Grpc.Examples.MathClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("0.1.*")]
diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
index 767340d6f2..85f213cb39 100644
--- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
+++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
@@ -58,10 +58,17 @@ namespace math.Tests
server = new Server();
server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl()));
- int port = server.AddPort(host + ":0");
+ int port = server.AddListeningPort(host + ":0");
server.Start();
channel = new Channel(host + ":" + port);
- client = MathGrpc.NewStub(channel);
+
+ // TODO: get rid of the custom header here once we have dedicated tests
+ // for header support.
+ var stubConfig = new StubConfiguration((headerBuilder) =>
+ {
+ headerBuilder.Add(new Metadata.MetadataEntry("customHeader", "abcdef"));
+ });
+ client = MathGrpc.NewStub(channel, stubConfig);
}
[TestFixtureTearDown]
@@ -105,7 +112,7 @@ namespace math.Tests
var recorder = new RecordingObserver<Num>();
client.Fib(new FibArgs.Builder { Limit = 6 }.Build(), recorder);
- CollectionAssert.AreEqual(new List<long>{1, 1, 2, 3, 5, 8},
+ CollectionAssert.AreEqual(new List<long> { 1, 1, 2, 3, 5, 8 },
recorder.ToList().Result.ConvertAll((n) => n.Num_));
}
@@ -114,7 +121,8 @@ namespace math.Tests
public void Sum()
{
var res = client.Sum();
- foreach (var num in new long[] { 10, 20, 30 }) {
+ foreach (var num in new long[] { 10, 20, 30 })
+ {
res.Inputs.OnNext(Num.CreateBuilder().SetNum_(num).Build());
}
res.Inputs.OnCompleted();
@@ -125,7 +133,8 @@ namespace math.Tests
[Test]
public void DivMany()
{
- List<DivArgs> divArgsList = new List<DivArgs>{
+ List<DivArgs> divArgsList = new List<DivArgs>
+ {
new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build(),
new DivArgs.Builder { Dividend = 100, Divisor = 21 }.Build(),
new DivArgs.Builder { Dividend = 7, Divisor = 2 }.Build()
@@ -142,9 +151,8 @@ namespace math.Tests
var result = recorder.ToList().Result;
- CollectionAssert.AreEqual(new long[] {3, 4, 3}, result.ConvertAll((divReply) => divReply.Quotient));
- CollectionAssert.AreEqual(new long[] {1, 16, 1}, result.ConvertAll((divReply) => divReply.Remainder));
+ CollectionAssert.AreEqual(new long[] { 3, 4, 3 }, result.ConvertAll((divReply) => divReply.Quotient));
+ CollectionAssert.AreEqual(new long[] { 1, 16, 1 }, result.ConvertAll((divReply) => divReply.Remainder));
}
}
}
-
diff --git a/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs
index 44b075ac0a..43c7616ac3 100644
--- a/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs
@@ -1,8 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
[assembly: AssemblyTitle("Grpc.Examples.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
@@ -11,12 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
diff --git a/src/csharp/Grpc.Examples/MathExamples.cs b/src/csharp/Grpc.Examples/MathExamples.cs
index 134270f6f7..b8bb7eacbd 100644
--- a/src/csharp/Grpc.Examples/MathExamples.cs
+++ b/src/csharp/Grpc.Examples/MathExamples.cs
@@ -71,7 +71,8 @@ namespace math
public static void SumExample(MathGrpc.IMathServiceClient stub)
{
List<Num> numbers = new List<Num>
- {new Num.Builder { Num_ = 1 }.Build(),
+ {
+ new Num.Builder { Num_ = 1 }.Build(),
new Num.Builder { Num_ = 2 }.Build(),
new Num.Builder { Num_ = 3 }.Build()
};
@@ -110,24 +111,12 @@ namespace math
public static void DependendRequestsExample(MathGrpc.IMathServiceClient stub)
{
var numberList = new List<Num>
- { new Num.Builder{ Num_ = 1 }.Build(),
- new Num.Builder{ Num_ = 2 }.Build(), new Num.Builder{ Num_ = 3 }.Build()
+ {
+ new Num.Builder { Num_ = 1 }.Build(),
+ new Num.Builder { Num_ = 2 }.Build(), new Num.Builder { Num_ = 3 }.Build()
};
numberList.ToObservable();
-
- //IObserver<Num> numbers;
- //Task<Num> call = stub.Sum(out numbers);
- //foreach (var num in numberList)
- //{
- // numbers.OnNext(num);
- //}
- //numbers.OnCompleted();
-
- //Num sum = call.Result;
-
- //DivReply result = stub.Div(new DivArgs.Builder { Dividend = sum.Num_, Divisor = numberList.Count }.Build());
}
}
}
-
diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs
index f938a24543..24e6a1de8e 100644
--- a/src/csharp/Grpc.Examples/MathGrpc.cs
+++ b/src/csharp/Grpc.Examples/MathGrpc.cs
@@ -45,35 +45,36 @@ namespace math
/// </summary>
public class MathGrpc
{
- readonly static Marshaller<DivArgs> divArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom);
- readonly static Marshaller<DivReply> divReplyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom);
- readonly static Marshaller<Num> numMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom);
- readonly static Marshaller<FibArgs> fibArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), FibArgs.ParseFrom);
+ static readonly string ServiceName = "/math.Math";
- readonly static Method<DivArgs, DivReply> divMethod = new Method<DivArgs, DivReply>(
+ static readonly Marshaller<DivArgs> DivArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom);
+ static readonly Marshaller<DivReply> DivReplyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom);
+ static readonly Marshaller<Num> NumMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom);
+ static readonly Marshaller<FibArgs> FibArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), FibArgs.ParseFrom);
+
+ static readonly Method<DivArgs, DivReply> DivMethod = new Method<DivArgs, DivReply>(
MethodType.Unary,
- "/math.Math/Div",
- divArgsMarshaller,
- divReplyMarshaller
- );
- readonly static Method<FibArgs, Num> fibMethod = new Method<FibArgs, Num>(
+ "Div",
+ DivArgsMarshaller,
+ DivReplyMarshaller);
+
+ static readonly Method<FibArgs, Num> FibMethod = new Method<FibArgs, Num>(
MethodType.ServerStreaming,
- "/math.Math/Fib",
- fibArgsMarshaller,
- numMarshaller
- );
- readonly static Method<Num, Num> sumMethod = new Method<Num, Num>(
+ "Fib",
+ FibArgsMarshaller,
+ NumMarshaller);
+
+ static readonly Method<Num, Num> SumMethod = new Method<Num, Num>(
MethodType.ClientStreaming,
- "/math.Math/Sum",
- numMarshaller,
- numMarshaller
- );
- readonly static Method<DivArgs, DivReply> divManyMethod = new Method<DivArgs, DivReply>(
+ "Sum",
+ NumMarshaller,
+ NumMarshaller);
+
+ static readonly Method<DivArgs, DivReply> DivManyMethod = new Method<DivArgs, DivReply>(
MethodType.DuplexStreaming,
- "/math.Math/DivMany",
- divArgsMarshaller,
- divReplyMarshaller
- );
+ "DivMany",
+ DivArgsMarshaller,
+ DivReplyMarshaller);
public interface IMathServiceClient
{
@@ -88,42 +89,43 @@ namespace math
IObserver<DivArgs> DivMany(IObserver<DivReply> responseObserver, CancellationToken token = default(CancellationToken));
}
- public class MathServiceClientStub : IMathServiceClient
+ public class MathServiceClientStub : AbstractStub<MathServiceClientStub, StubConfiguration>, IMathServiceClient
{
- readonly Channel channel;
+ public MathServiceClientStub(Channel channel) : this(channel, StubConfiguration.Default)
+ {
+ }
- public MathServiceClientStub(Channel channel)
+ public MathServiceClientStub(Channel channel, StubConfiguration config) : base(channel, config)
{
- this.channel = channel;
}
public DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<DivArgs, DivReply>(divMethod, channel);
+ var call = CreateCall(ServiceName, DivMethod);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<DivArgs, DivReply>(divMethod, channel);
+ var call = CreateCall(ServiceName, DivMethod);
return Calls.AsyncUnaryCall(call, request, token);
}
public void Fib(FibArgs request, IObserver<Num> responseObserver, CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<FibArgs, Num>(fibMethod, channel);
+ var call = CreateCall(ServiceName, FibMethod);
Calls.AsyncServerStreamingCall(call, request, responseObserver, token);
}
public ClientStreamingAsyncResult<Num, Num> Sum(CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<Num, Num>(sumMethod, channel);
+ var call = CreateCall(ServiceName, SumMethod);
return Calls.AsyncClientStreamingCall(call, token);
}
public IObserver<DivArgs> DivMany(IObserver<DivReply> responseObserver, CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<DivArgs, DivReply>(divManyMethod, channel);
+ var call = CreateCall(ServiceName, DivManyMethod);
return Calls.DuplexStreamingCall(call, responseObserver, token);
}
}
@@ -142,16 +144,21 @@ namespace math
public static ServerServiceDefinition BindService(IMathService serviceImpl)
{
- return ServerServiceDefinition.CreateBuilder("/math.Math/")
- .AddMethod(divMethod, serviceImpl.Div)
- .AddMethod(fibMethod, serviceImpl.Fib)
- .AddMethod(sumMethod, serviceImpl.Sum)
- .AddMethod(divManyMethod, serviceImpl.DivMany).Build();
+ return ServerServiceDefinition.CreateBuilder(ServiceName)
+ .AddMethod(DivMethod, serviceImpl.Div)
+ .AddMethod(FibMethod, serviceImpl.Fib)
+ .AddMethod(SumMethod, serviceImpl.Sum)
+ .AddMethod(DivManyMethod, serviceImpl.DivMany).Build();
}
public static IMathServiceClient NewStub(Channel channel)
{
return new MathServiceClientStub(channel);
}
+
+ public static IMathServiceClient NewStub(Channel channel, StubConfiguration config)
+ {
+ return new MathServiceClientStub(channel, config);
+ }
}
}
diff --git a/src/csharp/Grpc.Examples/MathServiceImpl.cs b/src/csharp/Grpc.Examples/MathServiceImpl.cs
index 76a08ce518..0b2357e0fa 100644
--- a/src/csharp/Grpc.Examples/MathServiceImpl.cs
+++ b/src/csharp/Grpc.Examples/MathServiceImpl.cs
@@ -73,8 +73,8 @@ namespace math
public IObserver<Num> Sum(IObserver<Num> responseObserver)
{
var recorder = new RecordingObserver<Num>();
- Task.Factory.StartNew(() => {
-
+ Task.Factory.StartNew(() =>
+ {
List<Num> inputs = recorder.ToList().Result;
long sum = 0;
@@ -104,7 +104,7 @@ namespace math
static IEnumerable<Num> FibInternal(long n)
{
long a = 1;
- yield return new Num.Builder { Num_=a }.Build();
+ yield return new Num.Builder { Num_ = a }.Build();
long b = 1;
for (long i = 0; i < n - 1; i++)
@@ -112,12 +112,12 @@ namespace math
long temp = a;
a = b;
b = temp + b;
- yield return new Num.Builder { Num_=a }.Build();
+ yield return new Num.Builder { Num_ = a }.Build();
}
}
- private class DivObserver : IObserver<DivArgs> {
-
+ private class DivObserver : IObserver<DivArgs>
+ {
readonly IObserver<DivReply> responseObserver;
public DivObserver(IObserver<DivReply> responseObserver)
@@ -142,4 +142,3 @@ namespace math
}
}
}
-
diff --git a/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs
index 7603db7ffd..b55d24166c 100644
--- a/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs
@@ -1,22 +1,12 @@
using System.Reflection;
using System.Runtime.CompilerServices;
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
-[assembly: AssemblyTitle ("Grpc.Examples")]
-[assembly: AssemblyDescription ("")]
-[assembly: AssemblyConfiguration ("")]
-[assembly: AssemblyCompany ("")]
-[assembly: AssemblyProduct ("")]
-[assembly: AssemblyCopyright ("Google Inc. All rights reserved.")]
-[assembly: AssemblyTrademark ("")]
-[assembly: AssemblyCulture ("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-[assembly: AssemblyVersion ("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
+[assembly: AssemblyTitle("Grpc.Examples")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("0.1.*")]
diff --git a/src/csharp/Grpc.Examples/Settings.StyleCop b/src/csharp/Grpc.Examples/Settings.StyleCop
new file mode 100644
index 0000000000..e9b6e7172a
--- /dev/null
+++ b/src/csharp/Grpc.Examples/Settings.StyleCop
@@ -0,0 +1,10 @@
+<StyleCopSettings Version="105">
+ <SourceFileList>
+ <SourceFile>Math.cs</SourceFile>
+ <Settings>
+ <GlobalSettings>
+ <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
+ </GlobalSettings>
+ </Settings>
+ </SourceFileList>
+</StyleCopSettings> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs
index d1f9e8560d..c93dd1eb2f 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs
@@ -1,8 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
[assembly: AssemblyTitle("Grpc.IntegrationTesting.Client")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
@@ -11,12 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs
index 4ef93f328d..f3def1aea4 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs
@@ -1,8 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
[assembly: AssemblyTitle("Grpc.IntegrationTesting.Server")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
@@ -11,12 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index 8f7a17efcb..c3e5f03074 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -39,6 +39,9 @@
<Reference Include="Google.ProtocolBuffers">
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath>
</Reference>
+ <Reference Include="System.Collections.Immutable">
+ <HintPath>..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -49,6 +52,7 @@
<Compile Include="TestServiceImpl.cs" />
<Compile Include="InteropServer.cs" />
<Compile Include="InteropClient.cs" />
+ <Compile Include="TestCredentials.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
@@ -75,8 +79,5 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
- <ItemGroup>
- <Folder Include="proto\" />
- <Folder Include="data\" />
- </ItemGroup>
-</Project>
+ <ItemGroup />
+</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index 30301f165b..6b92d3c660 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -38,10 +38,10 @@ 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;
-using grpc.testing;
namespace Grpc.IntegrationTesting
{
@@ -50,8 +50,8 @@ namespace Grpc.IntegrationTesting
private class ClientOptions
{
public bool help;
- public string serverHost= "127.0.0.1";
- public string serverHostOverride = "foo.test.google.fr";
+ public string serverHost = "127.0.0.1";
+ public string serverHostOverride = TestCredentials.DefaultHostOverride;
public int? serverPort;
public string testCase = "large_unary";
public bool useTls;
@@ -103,22 +103,13 @@ namespace Grpc.IntegrationTesting
Credentials credentials = null;
if (options.useTls)
{
- string caPath = "data/ca.pem"; // Default testing CA
- if (!options.useTestCa)
- {
- caPath = Environment.GetEnvironmentVariable("SSL_CERT_FILE");
- if (string.IsNullOrEmpty(caPath))
- {
- throw new ArgumentException("CA path environment variable is not set.");
- }
- }
- credentials = new SslCredentials(File.ReadAllText(caPath));
+ credentials = TestCredentials.CreateTestClientCredentials(options.useTestCa);
}
ChannelArgs channelArgs = null;
if (!string.IsNullOrEmpty(options.serverHostOverride))
{
- channelArgs = ChannelArgs.NewBuilder()
+ channelArgs = ChannelArgs.CreateBuilder()
.AddString(ChannelArgs.SslTargetNameOverrideKey, options.serverHostOverride).Build();
}
@@ -189,7 +180,7 @@ namespace Grpc.IntegrationTesting
{
Console.WriteLine("running client_streaming");
- var bodySizes = new List<int>{27182, 8, 1828, 45904};
+ var bodySizes = new List<int> { 27182, 8, 1828, 45904 };
var context = client.StreamingInputCall();
foreach (var size in bodySizes)
@@ -208,7 +199,7 @@ namespace Grpc.IntegrationTesting
{
Console.WriteLine("running server_streaming");
- var bodySizes = new List<int>{31415, 9, 2653, 58979};
+ var bodySizes = new List<int> { 31415, 9, 2653, 58979 };
var request = StreamingOutputCallRequest.CreateBuilder()
.SetResponseType(PayloadType.COMPRESSABLE)
@@ -265,7 +256,6 @@ namespace Grpc.IntegrationTesting
Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
Assert.AreEqual(2653, response.Payload.Body.Length);
-
inputs.OnNext(StreamingOutputCallRequest.CreateBuilder()
.SetResponseType(PayloadType.COMPRESSABLE)
.AddResponseParameters(ResponseParameters.CreateBuilder().SetSize(58979))
@@ -301,17 +291,18 @@ namespace Grpc.IntegrationTesting
public static void RunBenchmarkEmptyUnary(TestServiceGrpc.ITestServiceClient client)
{
BenchmarkUtil.RunBenchmark(10000, 10000,
- () => { client.EmptyCall(Empty.DefaultInstance);});
+ () => { client.EmptyCall(Empty.DefaultInstance); });
}
- private static Payload CreateZerosPayload(int size) {
+ private static Payload CreateZerosPayload(int size)
+ {
return Payload.CreateBuilder().SetBody(ByteString.CopyFrom(new byte[size])).Build();
}
private static ClientOptions ParseArguments(string[] args)
{
var options = new ClientOptions();
- foreach(string arg in args)
+ foreach (string arg in args)
{
ParseArgument(arg, options);
if (options.help)
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
index 4bb0b9ee51..1e76d3df21 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
@@ -35,10 +35,10 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using grpc.testing;
using Grpc.Core;
using Grpc.Core.Utils;
using NUnit.Framework;
-using grpc.testing;
namespace Grpc.IntegrationTesting
{
@@ -59,9 +59,13 @@ namespace Grpc.IntegrationTesting
server = new Server();
server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl()));
- int port = server.AddPort(host + ":0");
+ int port = server.AddListeningPort(host + ":0", TestCredentials.CreateTestServerCredentials());
server.Start();
- channel = new Channel(host + ":" + port);
+
+ var channelArgs = ChannelArgs.CreateBuilder()
+ .AddString(ChannelArgs.SslTargetNameOverrideKey, TestCredentials.DefaultHostOverride).Build();
+
+ channel = new Channel(host + ":" + port, TestCredentials.CreateTestClientCredentials(true), channelArgs);
client = TestServiceGrpc.NewStub(channel);
}
@@ -113,7 +117,5 @@ namespace Grpc.IntegrationTesting
// TODO: add cancel_after_begin
// TODO: add cancel_after_first_response
-
}
}
-
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
index a25d3b3530..ad5200774f 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
@@ -34,13 +34,14 @@
using System;
using System.Collections.Generic;
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;
-using grpc.testing;
namespace Grpc.IntegrationTesting
{
@@ -49,7 +50,7 @@ namespace Grpc.IntegrationTesting
private class ServerOptions
{
public bool help;
- public int? port;
+ public int? port = 8070;
public bool useTls;
}
@@ -93,7 +94,14 @@ namespace Grpc.IntegrationTesting
server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl()));
string addr = "0.0.0.0:" + options.port;
- server.AddPort(addr);
+ if (options.useTls)
+ {
+ server.AddListeningPort(addr, TestCredentials.CreateTestServerCredentials());
+ }
+ else
+ {
+ server.AddListeningPort(addr);
+ }
Console.WriteLine("Running server on " + addr);
server.Start();
@@ -105,7 +113,7 @@ namespace Grpc.IntegrationTesting
private static ServerOptions ParseArguments(string[] args)
{
var options = new ServerOptions();
- foreach(string arg in args)
+ foreach (string arg in args)
{
ParseArgument(arg, options);
if (options.help)
diff --git a/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs
index f633c19132..f09a448e9e 100644
--- a/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs
@@ -1,8 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
[assembly: AssemblyTitle("Grpc.IntegrationTesting")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
@@ -11,12 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
diff --git a/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop b/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop
new file mode 100644
index 0000000000..fb99cd4af1
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop
@@ -0,0 +1,11 @@
+<StyleCopSettings Version="105">
+ <SourceFileList>
+ <SourceFile>Messages.cs</SourceFile>
+ <SourceFile>Empty.cs</SourceFile>
+ <Settings>
+ <GlobalSettings>
+ <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
+ </GlobalSettings>
+ </Settings>
+ </SourceFileList>
+</StyleCopSettings> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
new file mode 100644
index 0000000000..401c50b1ae
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
@@ -0,0 +1,84 @@
+#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.Collections.Immutable;
+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;
+
+namespace Grpc.IntegrationTesting
+{
+ /// <summary>
+ /// SSL Credentials for testing.
+ /// </summary>
+ public static class TestCredentials
+ {
+ public const string DefaultHostOverride = "foo.test.google.fr";
+
+ public const string ClientCertAuthorityPath = "data/ca.pem";
+ public const string ClientCertAuthorityEnvName = "SSL_CERT_FILE";
+
+ public const string ServerCertChainPath = "data/server1.pem";
+ public const string ServerPrivateKeyPath = "data/server1.key";
+
+ public static SslCredentials CreateTestClientCredentials(bool useTestCa)
+ {
+ string caPath = ClientCertAuthorityPath;
+ if (!useTestCa)
+ {
+ caPath = Environment.GetEnvironmentVariable(ClientCertAuthorityEnvName);
+ if (string.IsNullOrEmpty(caPath))
+ {
+ throw new ArgumentException("CA path environment variable is not set.");
+ }
+ }
+ return new SslCredentials(File.ReadAllText(caPath));
+ }
+
+ public static SslServerCredentials CreateTestServerCredentials()
+ {
+ var keyCertPair = new KeyCertificatePair(
+ File.ReadAllText(ServerCertChainPath),
+ File.ReadAllText(ServerPrivateKeyPath));
+ return new SslServerCredentials(ImmutableList.Create(keyCertPair));
+ }
+ }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
index b71704bcc7..f63e0361a4 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
@@ -44,50 +44,51 @@ namespace grpc.testing
/// </summary>
public class TestServiceGrpc
{
- readonly static Marshaller<Empty> emptyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Empty.ParseFrom);
- readonly static Marshaller<SimpleRequest> simpleRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleRequest.ParseFrom);
- readonly static Marshaller<SimpleResponse> simpleResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleResponse.ParseFrom);
- readonly static Marshaller<StreamingOutputCallRequest> streamingOutputCallRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallRequest.ParseFrom);
- readonly static Marshaller<StreamingOutputCallResponse> streamingOutputCallResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallResponse.ParseFrom);
- readonly static Marshaller<StreamingInputCallRequest> streamingInputCallRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallRequest.ParseFrom);
- readonly static Marshaller<StreamingInputCallResponse> streamingInputCallResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallResponse.ParseFrom);
-
- readonly static Method<Empty, Empty> emptyCallMethod = new Method<Empty, Empty>(
+ static readonly string ServiceName = "/grpc.testing.TestService";
+
+ static readonly Marshaller<Empty> EmptyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Empty.ParseFrom);
+ static readonly Marshaller<SimpleRequest> SimpleRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleRequest.ParseFrom);
+ static readonly Marshaller<SimpleResponse> SimpleResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleResponse.ParseFrom);
+ static readonly Marshaller<StreamingOutputCallRequest> StreamingOutputCallRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallRequest.ParseFrom);
+ static readonly Marshaller<StreamingOutputCallResponse> StreamingOutputCallResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallResponse.ParseFrom);
+ static readonly Marshaller<StreamingInputCallRequest> StreamingInputCallRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallRequest.ParseFrom);
+ static readonly Marshaller<StreamingInputCallResponse> StreamingInputCallResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallResponse.ParseFrom);
+
+ static readonly Method<Empty, Empty> EmptyCallMethod = new Method<Empty, Empty>(
MethodType.Unary,
- "/grpc.testing.TestService/EmptyCall",
- emptyMarshaller,
- emptyMarshaller
- );
- readonly static Method<SimpleRequest, SimpleResponse> unaryCallMethod = new Method<SimpleRequest, SimpleResponse>(
+ "EmptyCall",
+ EmptyMarshaller,
+ EmptyMarshaller);
+
+ static readonly Method<SimpleRequest, SimpleResponse> UnaryCallMethod = new Method<SimpleRequest, SimpleResponse>(
MethodType.Unary,
- "/grpc.testing.TestService/UnaryCall",
- simpleRequestMarshaller,
- simpleResponseMarshaller
- );
- readonly static Method<StreamingOutputCallRequest, StreamingOutputCallResponse> streamingOutputCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
+ "UnaryCall",
+ SimpleRequestMarshaller,
+ SimpleResponseMarshaller);
+
+ static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> StreamingOutputCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.ServerStreaming,
- "/grpc.testing.TestService/StreamingOutputCall",
- streamingOutputCallRequestMarshaller,
- streamingOutputCallResponseMarshaller
- );
- readonly static Method<StreamingInputCallRequest, StreamingInputCallResponse> streamingInputCallMethod = new Method<StreamingInputCallRequest, StreamingInputCallResponse>(
+ "StreamingOutputCall",
+ StreamingOutputCallRequestMarshaller,
+ StreamingOutputCallResponseMarshaller);
+
+ static readonly Method<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCallMethod = new Method<StreamingInputCallRequest, StreamingInputCallResponse>(
MethodType.ClientStreaming,
- "/grpc.testing.TestService/StreamingInputCall",
- streamingInputCallRequestMarshaller,
- streamingInputCallResponseMarshaller
- );
- readonly static Method<StreamingOutputCallRequest, StreamingOutputCallResponse> fullDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
+ "StreamingInputCall",
+ StreamingInputCallRequestMarshaller,
+ StreamingInputCallResponseMarshaller);
+
+ static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.DuplexStreaming,
- "/grpc.testing.TestService/FullDuplexCall",
- streamingOutputCallRequestMarshaller,
- streamingOutputCallResponseMarshaller
- );
- readonly static Method<StreamingOutputCallRequest, StreamingOutputCallResponse> halfDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
+ "FullDuplexCall",
+ StreamingOutputCallRequestMarshaller,
+ StreamingOutputCallResponseMarshaller);
+
+ static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.DuplexStreaming,
- "/grpc.testing.TestService/HalfDuplexCall",
- streamingOutputCallRequestMarshaller,
- streamingOutputCallResponseMarshaller
- );
+ "HalfDuplexCall",
+ StreamingOutputCallRequestMarshaller,
+ StreamingOutputCallResponseMarshaller);
public interface ITestServiceClient
{
@@ -108,60 +109,61 @@ namespace grpc.testing
IObserver<StreamingOutputCallRequest> HalfDuplexCall(IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken));
}
- public class TestServiceClientStub : ITestServiceClient
+ public class TestServiceClientStub : AbstractStub<TestServiceClientStub, StubConfiguration>, ITestServiceClient
{
- readonly Channel channel;
+ public TestServiceClientStub(Channel channel) : base(channel, StubConfiguration.Default)
+ {
+ }
- public TestServiceClientStub(Channel channel)
+ public TestServiceClientStub(Channel channel, StubConfiguration config) : base(channel, config)
{
- this.channel = channel;
}
public Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<Empty, Empty>(emptyCallMethod, channel);
+ var call = CreateCall(ServiceName, EmptyCallMethod);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<Empty> EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<Empty, Empty>(emptyCallMethod, channel);
+ var call = CreateCall(ServiceName, EmptyCallMethod);
return Calls.AsyncUnaryCall(call, request, token);
}
public SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<SimpleRequest, SimpleResponse>(unaryCallMethod, channel);
+ var call = CreateCall(ServiceName, UnaryCallMethod);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<SimpleResponse> UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<SimpleRequest, SimpleResponse>(unaryCallMethod, channel);
+ var call = CreateCall(ServiceName, UnaryCallMethod);
return Calls.AsyncUnaryCall(call, request, token);
}
- public void StreamingOutputCall(StreamingOutputCallRequest request, IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken)) {
- var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(streamingOutputCallMethod, channel);
+ public void StreamingOutputCall(StreamingOutputCallRequest request, IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken))
+ {
+ var call = CreateCall(ServiceName, StreamingOutputCallMethod);
Calls.AsyncServerStreamingCall(call, request, responseObserver, token);
}
public ClientStreamingAsyncResult<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<StreamingInputCallRequest, StreamingInputCallResponse>(streamingInputCallMethod, channel);
+ var call = CreateCall(ServiceName, StreamingInputCallMethod);
return Calls.AsyncClientStreamingCall(call, token);
}
public IObserver<StreamingOutputCallRequest> FullDuplexCall(IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(fullDuplexCallMethod, channel);
+ var call = CreateCall(ServiceName, FullDuplexCallMethod);
return Calls.DuplexStreamingCall(call, responseObserver, token);
}
-
public IObserver<StreamingOutputCallRequest> HalfDuplexCall(IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken))
{
- var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(halfDuplexCallMethod, channel);
+ var call = CreateCall(ServiceName, HalfDuplexCallMethod);
return Calls.DuplexStreamingCall(call, responseObserver, token);
}
}
@@ -184,13 +186,13 @@ namespace grpc.testing
public static ServerServiceDefinition BindService(ITestService serviceImpl)
{
- return ServerServiceDefinition.CreateBuilder("/grpc.testing.TestService/")
- .AddMethod(emptyCallMethod, serviceImpl.EmptyCall)
- .AddMethod(unaryCallMethod, serviceImpl.UnaryCall)
- .AddMethod(streamingOutputCallMethod, serviceImpl.StreamingOutputCall)
- .AddMethod(streamingInputCallMethod, serviceImpl.StreamingInputCall)
- .AddMethod(fullDuplexCallMethod, serviceImpl.FullDuplexCall)
- .AddMethod(halfDuplexCallMethod, serviceImpl.HalfDuplexCall)
+ return ServerServiceDefinition.CreateBuilder(ServiceName)
+ .AddMethod(EmptyCallMethod, serviceImpl.EmptyCall)
+ .AddMethod(UnaryCallMethod, serviceImpl.UnaryCall)
+ .AddMethod(StreamingOutputCallMethod, serviceImpl.StreamingOutputCall)
+ .AddMethod(StreamingInputCallMethod, serviceImpl.StreamingInputCall)
+ .AddMethod(FullDuplexCallMethod, serviceImpl.FullDuplexCall)
+ .AddMethod(HalfDuplexCallMethod, serviceImpl.HalfDuplexCall)
.Build();
}
diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
index 176843b130..661b31b0ee 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
@@ -55,14 +55,14 @@ namespace grpc.testing
{
var response = SimpleResponse.CreateBuilder()
.SetPayload(CreateZerosPayload(request.ResponseSize)).Build();
- //TODO: check we support ReponseType
+ // TODO: check we support ReponseType
responseObserver.OnNext(response);
responseObserver.OnCompleted();
}
public void StreamingOutputCall(StreamingOutputCallRequest request, IObserver<StreamingOutputCallResponse> responseObserver)
{
- foreach(var responseParam in request.ResponseParametersList)
+ foreach (var responseParam in request.ResponseParametersList)
{
var response = StreamingOutputCallResponse.CreateBuilder()
.SetPayload(CreateZerosPayload(responseParam.Size)).Build();
@@ -74,9 +74,10 @@ namespace grpc.testing
public IObserver<StreamingInputCallRequest> StreamingInputCall(IObserver<StreamingInputCallResponse> responseObserver)
{
var recorder = new RecordingObserver<StreamingInputCallRequest>();
- Task.Run(() => {
+ Task.Run(() =>
+ {
int sum = 0;
- foreach(var req in recorder.ToList().Result)
+ foreach (var req in recorder.ToList().Result)
{
sum += req.Payload.Body.Length;
}
@@ -98,8 +99,8 @@ namespace grpc.testing
throw new NotImplementedException();
}
- private class FullDuplexObserver : IObserver<StreamingOutputCallRequest> {
-
+ private class FullDuplexObserver : IObserver<StreamingOutputCallRequest>
+ {
readonly IObserver<StreamingOutputCallResponse> responseObserver;
public FullDuplexObserver(IObserver<StreamingOutputCallResponse> responseObserver)
@@ -119,22 +120,18 @@ namespace grpc.testing
public void OnNext(StreamingOutputCallRequest value)
{
- // TODO: this is not in order!!!
- //Task.Factory.StartNew(() => {
-
- foreach(var responseParam in value.ResponseParametersList)
- {
- var response = StreamingOutputCallResponse.CreateBuilder()
- .SetPayload(CreateZerosPayload(responseParam.Size)).Build();
- responseObserver.OnNext(response);
- }
- //});
+ foreach (var responseParam in value.ResponseParametersList)
+ {
+ var response = StreamingOutputCallResponse.CreateBuilder()
+ .SetPayload(CreateZerosPayload(responseParam.Size)).Build();
+ responseObserver.OnNext(response);
+ }
}
}
- private static Payload CreateZerosPayload(int size) {
+ private static Payload CreateZerosPayload(int size)
+ {
return Payload.CreateBuilder().SetBody(ByteString.CopyFrom(new byte[size])).Build();
}
}
}
-
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index 51c17bcd5e..157c264eac 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -2,4 +2,5 @@
<packages>
<package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" />
<package id="NUnit" version="2.6.4" targetFramework="net45" />
+ <package id="System.Collections.Immutable" version="1.1.34-rc" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Settings.StyleCop b/src/csharp/Settings.StyleCop
new file mode 100644
index 0000000000..2ecf22f69e
--- /dev/null
+++ b/src/csharp/Settings.StyleCop
@@ -0,0 +1,509 @@
+<StyleCopSettings Version="105">
+ <Analyzers>
+ <Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
+ <Rules>
+ <Rule Name="ElementsMustBeDocumented">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="PartialElementsMustBeDocumented">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="EnumerationItemsMustBeDocumented">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="DocumentationMustContainValidXml">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementDocumentationMustHaveSummary">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="PartialElementDocumentationMustHaveSummary">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementDocumentationMustHaveSummaryText">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="PartialElementDocumentationMustHaveSummaryText">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementDocumentationMustNotHaveDefaultSummary">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementParametersMustBeDocumented">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementParameterDocumentationMustMatchElementParameters">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementParameterDocumentationMustDeclareParameterName">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementParameterDocumentationMustHaveText">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementReturnValueMustBeDocumented">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementReturnValueDocumentationMustHaveText">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="VoidReturnValueMustNotBeDocumented">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="GenericTypeParametersMustBeDocumented">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="GenericTypeParametersMustBeDocumentedPartialClass">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="GenericTypeParameterDocumentationMustMatchTypeParameters">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="GenericTypeParameterDocumentationMustDeclareParameterName">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="GenericTypeParameterDocumentationMustHaveText">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="PropertySummaryDocumentationMustMatchAccessors">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="PropertySummaryDocumentationMustOmitSetAccessorWithRestrictedAccess">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementDocumentationMustNotBeCopiedAndPasted">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="SingleLineCommentsMustNotUseDocumentationStyleSlashes">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="DocumentationTextMustNotBeEmpty">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="DocumentationTextMustContainWhitespace">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="DocumentationMustMeetCharacterPercentage">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ConstructorSummaryDocumentationMustBeginWithStandardText">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="DestructorSummaryDocumentationMustBeginWithStandardText">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="DocumentationHeadersMustNotContainBlankLines">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="IncludedDocumentationXPathDoesNotExist">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="IncludeNodeDoesNotContainValidFileAndPath">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="InheritDocMustBeUsedWithInheritingClass">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementDocumentationMustBeSpelledCorrectly">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FileMustHaveHeader">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FileHeaderMustShowCopyright">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FileHeaderMustHaveCopyrightText">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FileHeaderMustContainFileName">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FileHeaderFileNameDocumentationMustMatchFileName">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FileHeaderMustHaveValidCompanyText">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FileHeaderFileNameDocumentationMustMatchTypeName">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ </Rules>
+ <AnalyzerSettings />
+ </Analyzer>
+ <Analyzer AnalyzerId="StyleCop.CSharp.MaintainabilityRules">
+ <Rules>
+ <Rule Name="AccessModifierMustBeDeclared">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FieldsMustBePrivate">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="CodeAnalysisSuppressionMustHaveJustification">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="DebugAssertMustProvideMessageText">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="DebugFailMustProvideMessageText">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FileMayOnlyContainASingleClass">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="StatementMustNotUseUnnecessaryParenthesis">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ArithmeticExpressionsMustDeclarePrecedence">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ConditionalExpressionsMustDeclarePrecedence">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="RemoveDelegateParenthesisWhenPossible">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="AttributeConstructorMustNotUseUnnecessaryParenthesis">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="RemoveUnnecessaryCode">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ </Rules>
+ <AnalyzerSettings />
+ </Analyzer>
+ <Analyzer AnalyzerId="StyleCop.CSharp.NamingRules">
+ <Rules>
+ <Rule Name="NonPrivateReadonlyFieldsMustBeginWithUpperCaseLetter">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FieldNamesMustNotUseHungarianNotation">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FieldNamesMustBeginWithLowerCaseLetter">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="AccessibleFieldsMustBeginWithUpperCaseLetter">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="VariableNamesMustNotBePrefixed">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FieldNamesMustNotBeginWithUnderscore">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="FieldNamesMustNotContainUnderscore">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementMustBeginWithUpperCaseLetter">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ </Rules>
+ <AnalyzerSettings />
+ </Analyzer>
+ <Analyzer AnalyzerId="StyleCop.CSharp.OrderingRules">
+ <Rules>
+ <Rule Name="UsingDirectivesMustBePlacedWithinNamespace">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementsMustAppearInTheCorrectOrder">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementsMustBeOrderedByAccess">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="StaticElementsMustAppearBeforeInstanceElements">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="PropertyAccessorsMustFollowOrder">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="EventAccessorsMustFollowOrder">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="UsingAliasDirectivesMustBePlacedAfterOtherUsingDirectives">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="UsingAliasDirectivesMustBeOrderedAlphabeticallyByAliasName">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ </Rules>
+ <AnalyzerSettings />
+ </Analyzer>
+ <Analyzer AnalyzerId="StyleCop.CSharp.ReadabilityRules">
+ <Rules>
+ <Rule Name="DoNotPrefixCallsWithBaseUnlessLocalImplementationExists">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="PrefixLocalCallsWithThis">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="PrefixCallsCorrectly">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="OpeningParenthesisMustBeOnDeclarationLine">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ClosingParenthesisMustBeOnLineOfLastParameter">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ClosingParenthesisMustBeOnLineOfOpeningParenthesis">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="CommaMustBeOnSameLineAsPreviousParameter">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ParameterListMustFollowDeclaration">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ParameterMustFollowComma">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="SplitParametersMustStartOnLineAfterDeclaration">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ParametersMustBeOnSameLineOrSeparateLines">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ParameterMustNotSpanMultipleLines">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="QueryClauseMustFollowPreviousClause">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="QueryClausesMustBeOnSeparateLinesOrAllOnOneLine">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="QueryClauseMustBeginOnNewLineWhenPreviousClauseSpansMultipleLines">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="QueryClausesSpanningMultipleLinesMustBeginOnOwnLine">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="CodeMustNotContainEmptyStatements">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="CodeMustNotContainMultipleStatementsOnOneLine">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="BlockStatementsMustNotContainEmbeddedComments">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="BlockStatementsMustNotContainEmbeddedRegions">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="UseStringEmptyForEmptyStrings">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ </Rules>
+ <AnalyzerSettings />
+ </Analyzer>
+ <Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules">
+ <Rules>
+ <Rule Name="SingleLineCommentsMustNotBeFollowedByBlankLine">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ClosingCurlyBracketMustBeFollowedByBlankLine">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="ElementDocumentationHeaderMustBePrecededByBlankLine">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ <Rule Name="SingleLineCommentMustBePrecededByBlankLine">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ </Rules>
+ <AnalyzerSettings />
+ </Analyzer>
+ </Analyzers>
+</StyleCopSettings> \ No newline at end of file
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index e24438704c..9a1c908d11 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -102,34 +102,114 @@ grpcsharp_batch_context *grpcsharp_batch_context_create() {
return ctx;
}
-/**
- * Destroys metadata array including keys and values.
+/*
+ * Destroys array->metadata.
+ * The array pointer itself is not freed.
*/
-void grpcsharp_metadata_array_destroy_recursive(grpc_metadata_array *array) {
- if (!array->metadata) {
+void grpcsharp_metadata_array_destroy_metadata_only(
+ grpc_metadata_array *array) {
+ gpr_free(array->metadata);
+}
+
+/*
+ * Destroys keys, values and array->metadata.
+ * The array pointer itself is not freed.
+ */
+void grpcsharp_metadata_array_destroy_metadata_including_entries(
+ grpc_metadata_array *array) {
+ size_t i;
+ if (array->metadata) {
+ for (i = 0; i < array->count; i++) {
+ gpr_free((void *)array->metadata[i].key);
+ gpr_free((void *)array->metadata[i].value);
+ }
+ }
+ gpr_free(array->metadata);
+}
+
+/*
+ * Fully destroys the metadata array.
+ */
+GPR_EXPORT void GPR_CALLTYPE
+grpcsharp_metadata_array_destroy_full(grpc_metadata_array *array) {
+ if (!array) {
return;
}
- /* TODO: destroy also keys and values */
- grpc_metadata_array_destroy(array);
+ grpcsharp_metadata_array_destroy_metadata_including_entries(array);
+ gpr_free(array);
+}
+
+/*
+ * Creates an empty metadata array with given capacity.
+ * Array can later be destroyed by grpc_metadata_array_destroy_full.
+ */
+GPR_EXPORT grpc_metadata_array *GPR_CALLTYPE
+grpcsharp_metadata_array_create(size_t capacity) {
+ grpc_metadata_array *array =
+ (grpc_metadata_array *)gpr_malloc(sizeof(grpc_metadata_array));
+ grpc_metadata_array_init(array);
+ array->capacity = capacity;
+ array->count = 0;
+ if (capacity > 0) {
+ array->metadata =
+ (grpc_metadata *)gpr_malloc(sizeof(grpc_metadata) * capacity);
+ memset(array->metadata, 0, sizeof(grpc_metadata) * capacity);
+ } else {
+ array->metadata = NULL;
+ }
+ return array;
+}
+
+GPR_EXPORT void GPR_CALLTYPE
+grpcsharp_metadata_array_add(grpc_metadata_array *array, const char *key,
+ const char *value, size_t value_length) {
+ size_t i = array->count;
+ GPR_ASSERT(array->count < array->capacity);
+ array->metadata[i].key = gpr_strdup(key);
+ array->metadata[i].value = (char *)gpr_malloc(value_length);
+ memcpy((void *)array->metadata[i].value, value, value_length);
+ array->metadata[i].value_length = value_length;
+ array->count++;
+}
+
+/* Move contents of metadata array */
+void grpcsharp_metadata_array_move(grpc_metadata_array *dest,
+ grpc_metadata_array *src) {
+ if (!src) {
+ dest->capacity = 0;
+ dest->count = 0;
+ dest->metadata = NULL;
+ return;
+ }
+
+ dest->capacity = src->capacity;
+ dest->count = src->count;
+ dest->metadata = src->metadata;
+
+ src->capacity = 0;
+ src->count = 0;
+ src->metadata = NULL;
}
void grpcsharp_batch_context_destroy(grpcsharp_batch_context *ctx) {
if (!ctx) {
return;
}
- grpcsharp_metadata_array_destroy_recursive(&(ctx->send_initial_metadata));
+ grpcsharp_metadata_array_destroy_metadata_including_entries(
+ &(ctx->send_initial_metadata));
grpc_byte_buffer_destroy(ctx->send_message);
- grpcsharp_metadata_array_destroy_recursive(
+ grpcsharp_metadata_array_destroy_metadata_including_entries(
&(ctx->send_status_from_server.trailing_metadata));
gpr_free(ctx->send_status_from_server.status_details);
- grpc_metadata_array_destroy(&(ctx->recv_initial_metadata));
+ grpcsharp_metadata_array_destroy_metadata_only(&(ctx->recv_initial_metadata));
grpc_byte_buffer_destroy(ctx->recv_message);
- grpc_metadata_array_destroy(&(ctx->recv_status_on_client.trailing_metadata));
+ grpcsharp_metadata_array_destroy_metadata_only(
+ &(ctx->recv_status_on_client.trailing_metadata));
gpr_free((void *)ctx->recv_status_on_client.status_details);
/* NOTE: ctx->server_rpc_new.call is not destroyed because callback handler is
@@ -137,7 +217,8 @@ void grpcsharp_batch_context_destroy(grpcsharp_batch_context *ctx) {
to take its ownership. */
grpc_call_details_destroy(&(ctx->server_rpc_new.call_details));
- grpc_metadata_array_destroy(&(ctx->server_rpc_new.request_metadata));
+ grpcsharp_metadata_array_destroy_metadata_only(
+ &(ctx->server_rpc_new.request_metadata));
gpr_free(ctx);
}
@@ -346,17 +427,19 @@ grpcsharp_call_start_write_from_copied_buffer(grpc_call *call,
GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_start_unary(grpc_call *call, callback_funcptr callback,
- const char *send_buffer, size_t send_buffer_len) {
+ const char *send_buffer, size_t send_buffer_len,
+ grpc_metadata_array *initial_metadata) {
/* TODO: don't use magic number */
grpc_op ops[6];
grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
ctx->callback = callback;
- /* TODO: implement sending the metadata... */
ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
- /* ctx->send_initial_metadata is already zeroed out. */
- ops[0].data.send_initial_metadata.count = 0;
- ops[0].data.send_initial_metadata.metadata = NULL;
+ grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
+ initial_metadata);
+ ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
+ ops[0].data.send_initial_metadata.metadata =
+ ctx->send_initial_metadata.metadata;
ops[1].op = GRPC_OP_SEND_MESSAGE;
ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
@@ -389,9 +472,11 @@ GPR_EXPORT void GPR_CALLTYPE
grpcsharp_call_blocking_unary(grpc_call *call,
grpc_completion_queue *dedicated_cq,
callback_funcptr callback,
- const char *send_buffer, size_t send_buffer_len) {
+ const char *send_buffer, size_t send_buffer_len,
+ grpc_metadata_array *initial_metadata) {
GPR_ASSERT(grpcsharp_call_start_unary(call, callback, send_buffer,
- send_buffer_len) == GRPC_CALL_OK);
+ send_buffer_len,
+ initial_metadata) == GRPC_CALL_OK);
/* TODO: we would like to use pluck, but we don't know the tag */
GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) ==
@@ -403,17 +488,19 @@ grpcsharp_call_blocking_unary(grpc_call *call,
GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_start_client_streaming(grpc_call *call,
- callback_funcptr callback) {
+ callback_funcptr callback,
+ grpc_metadata_array *initial_metadata) {
/* TODO: don't use magic number */
grpc_op ops[4];
grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
ctx->callback = callback;
- /* TODO: implement sending the metadata... */
ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
- /* ctx->send_initial_metadata is already zeroed out. */
- ops[0].data.send_initial_metadata.count = 0;
- ops[0].data.send_initial_metadata.metadata = NULL;
+ grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
+ initial_metadata);
+ ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
+ ops[0].data.send_initial_metadata.metadata =
+ ctx->send_initial_metadata.metadata;
ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
ops[1].data.recv_initial_metadata = &(ctx->recv_initial_metadata);
@@ -435,21 +522,20 @@ grpcsharp_call_start_client_streaming(grpc_call *call,
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx);
}
-GPR_EXPORT grpc_call_error GPR_CALLTYPE
-grpcsharp_call_start_server_streaming(grpc_call *call,
- callback_funcptr callback,
- const char *send_buffer,
- size_t send_buffer_len) {
+GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
+ grpc_call *call, callback_funcptr callback, const char *send_buffer,
+ size_t send_buffer_len, grpc_metadata_array *initial_metadata) {
/* TODO: don't use magic number */
grpc_op ops[5];
grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
ctx->callback = callback;
- /* TODO: implement sending the metadata... */
ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
- /* ctx->send_initial_metadata is already zeroed out. */
- ops[0].data.send_initial_metadata.count = 0;
- ops[0].data.send_initial_metadata.metadata = NULL;
+ grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
+ initial_metadata);
+ ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
+ ops[0].data.send_initial_metadata.metadata =
+ ctx->send_initial_metadata.metadata;
ops[1].op = GRPC_OP_SEND_MESSAGE;
ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
@@ -476,17 +562,19 @@ grpcsharp_call_start_server_streaming(grpc_call *call,
GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_start_duplex_streaming(grpc_call *call,
- callback_funcptr callback) {
+ callback_funcptr callback,
+ grpc_metadata_array *initial_metadata) {
/* TODO: don't use magic number */
grpc_op ops[3];
grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
ctx->callback = callback;
- /* TODO: implement sending the metadata... */
ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
- /* ctx->send_initial_metadata is already zeroed out. */
- ops[0].data.send_initial_metadata.count = 0;
- ops[0].data.send_initial_metadata.metadata = NULL;
+ grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
+ initial_metadata);
+ ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
+ ops[0].data.send_initial_metadata.metadata =
+ ctx->send_initial_metadata.metadata;
ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
ops[1].data.recv_initial_metadata = &(ctx->recv_initial_metadata);
@@ -653,6 +741,41 @@ grpcsharp_secure_channel_create(grpc_credentials *creds, const char *target,
return grpc_secure_channel_create(creds, target, args);
}
+GPR_EXPORT grpc_server_credentials *GPR_CALLTYPE
+grpcsharp_ssl_server_credentials_create(
+ const char *pem_root_certs, const char **key_cert_pair_cert_chain_array,
+ const char **key_cert_pair_private_key_array, size_t num_key_cert_pairs) {
+ size_t i;
+ grpc_server_credentials *creds;
+ grpc_ssl_pem_key_cert_pair *key_cert_pairs =
+ gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
+ memset(key_cert_pairs, 0,
+ sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
+
+ for (i = 0; i < num_key_cert_pairs; i++) {
+ if (key_cert_pair_cert_chain_array[i] ||
+ key_cert_pair_private_key_array[i]) {
+ key_cert_pairs[i].cert_chain = key_cert_pair_cert_chain_array[i];
+ key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i];
+ }
+ }
+ creds = grpc_ssl_server_credentials_create(pem_root_certs, key_cert_pairs,
+ num_key_cert_pairs);
+ gpr_free(key_cert_pairs);
+ return creds;
+}
+
+GPR_EXPORT void grpcsharp_server_credentials_release(
+ grpc_server_credentials *creds) {
+ grpc_server_credentials_release(creds);
+}
+
+GPR_EXPORT gpr_int32 GPR_CALLTYPE
+grpcsharp_server_add_secure_http2_port(grpc_server *server, const char *addr,
+ grpc_server_credentials *creds) {
+ return grpc_server_add_secure_http2_port(server, addr, creds);
+}
+
/* Logging */
typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, gpr_int32 line,