aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/csharp
diff options
context:
space:
mode:
Diffstat (limited to 'src/csharp')
-rw-r--r--src/csharp/Grpc.Core.Tests/ClientServerTest.cs84
-rw-r--r--src/csharp/Grpc.Core.Tests/ServerTest.cs39
-rw-r--r--src/csharp/Grpc.Core.Tests/TimeoutsTest.cs40
-rw-r--r--src/csharp/Grpc.Core/CallInvocationDetails.cs (renamed from src/csharp/Grpc.Core/Call.cs)56
-rw-r--r--src/csharp/Grpc.Core/CallOptions.cs89
-rw-r--r--src/csharp/Grpc.Core/Calls.cs48
-rw-r--r--src/csharp/Grpc.Core/Channel.cs16
-rw-r--r--src/csharp/Grpc.Core/ChannelOptions.cs1
-rw-r--r--src/csharp/Grpc.Core/ClientBase.cs10
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.csproj11
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.nuspec1
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCall.cs84
-rw-r--r--src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs7
-rw-r--r--src/csharp/Grpc.Core/KeyCertificatePair.cs1
-rw-r--r--src/csharp/Grpc.Core/Metadata.cs1
-rw-r--r--src/csharp/Grpc.Core/Method.cs28
-rw-r--r--src/csharp/Grpc.Core/Server.cs175
-rw-r--r--src/csharp/Grpc.Core/ServerCallContext.cs15
-rw-r--r--src/csharp/Grpc.Core/ServerCredentials.cs28
-rw-r--r--src/csharp/Grpc.Core/ServerPort.cs120
-rw-r--r--src/csharp/Grpc.Core/ServerServiceDefinition.cs12
-rw-r--r--src/csharp/Grpc.Core/packages.config1
-rw-r--r--src/csharp/Grpc.Examples.MathServer/MathServer.cs15
-rw-r--r--src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs20
-rw-r--r--src/csharp/Grpc.Examples/MathGrpc.cs54
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs10
-rw-r--r--src/csharp/Grpc.HealthCheck/HealthGrpc.cs21
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj3
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs14
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropServer.cs10
-rw-r--r--src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs15
-rw-r--r--src/csharp/Grpc.IntegrationTesting/TestCredentials.cs1
-rw-r--r--src/csharp/Grpc.IntegrationTesting/TestGrpc.cs86
-rw-r--r--src/csharp/Grpc.IntegrationTesting/packages.config1
-rw-r--r--src/csharp/ext/grpc_csharp_ext.c10
35 files changed, 797 insertions, 330 deletions
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index 35924868ca..64ea21800f 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -46,23 +46,26 @@ namespace Grpc.Core.Tests
public class ClientServerTest
{
const string Host = "127.0.0.1";
- const string ServiceName = "/tests.Test";
+ const string ServiceName = "tests.Test";
static readonly Method<string, string> EchoMethod = new Method<string, string>(
MethodType.Unary,
- "/tests.Test/Echo",
+ ServiceName,
+ "Echo",
Marshallers.StringMarshaller,
Marshallers.StringMarshaller);
static readonly Method<string, string> ConcatAndEchoMethod = new Method<string, string>(
MethodType.ClientStreaming,
- "/tests.Test/ConcatAndEcho",
+ ServiceName,
+ "ConcatAndEcho",
Marshallers.StringMarshaller,
Marshallers.StringMarshaller);
static readonly Method<string, string> NonexistentMethod = new Method<string, string>(
MethodType.Unary,
- "/tests.Test/NonexistentMethod",
+ ServiceName,
+ "NonexistentMethod",
Marshallers.StringMarshaller,
Marshallers.StringMarshaller);
@@ -77,11 +80,13 @@ namespace Grpc.Core.Tests
[SetUp]
public void Init()
{
- server = new Server();
- server.AddServiceDefinition(ServiceDefinition);
- int port = server.AddPort(Host, Server.PickUnusedPort, ServerCredentials.Insecure);
+ server = new Server
+ {
+ Services = { ServiceDefinition },
+ Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
+ };
server.Start();
- channel = new Channel(Host, port, Credentials.Insecure);
+ channel = new Channel(Host, server.Ports.Single().BoundPort, Credentials.Insecure);
}
[TearDown]
@@ -100,17 +105,17 @@ namespace Grpc.Core.Tests
[Test]
public void UnaryCall()
{
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
- Assert.AreEqual("ABC", Calls.BlockingUnaryCall(internalCall, "ABC", CancellationToken.None));
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
+ Assert.AreEqual("ABC", Calls.BlockingUnaryCall(callDetails, "ABC"));
}
[Test]
public void UnaryCall_ServerHandlerThrows()
{
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try
{
- Calls.BlockingUnaryCall(internalCall, "THROW", CancellationToken.None);
+ Calls.BlockingUnaryCall(callDetails, "THROW");
Assert.Fail();
}
catch (RpcException e)
@@ -122,10 +127,10 @@ namespace Grpc.Core.Tests
[Test]
public void UnaryCall_ServerHandlerThrowsRpcException()
{
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try
{
- Calls.BlockingUnaryCall(internalCall, "THROW_UNAUTHENTICATED", CancellationToken.None);
+ Calls.BlockingUnaryCall(callDetails, "THROW_UNAUTHENTICATED");
Assert.Fail();
}
catch (RpcException e)
@@ -137,10 +142,10 @@ namespace Grpc.Core.Tests
[Test]
public void UnaryCall_ServerHandlerSetsStatus()
{
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try
{
- Calls.BlockingUnaryCall(internalCall, "SET_UNAUTHENTICATED", CancellationToken.None);
+ Calls.BlockingUnaryCall(callDetails, "SET_UNAUTHENTICATED");
Assert.Fail();
}
catch (RpcException e)
@@ -150,20 +155,20 @@ namespace Grpc.Core.Tests
}
[Test]
- public void AsyncUnaryCall()
+ public async Task AsyncUnaryCall()
{
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
- var result = Calls.AsyncUnaryCall(internalCall, "ABC", CancellationToken.None).ResponseAsync.Result;
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
+ var result = await Calls.AsyncUnaryCall(callDetails, "ABC");
Assert.AreEqual("ABC", result);
}
[Test]
public async Task AsyncUnaryCall_ServerHandlerThrows()
{
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
try
{
- await Calls.AsyncUnaryCall(internalCall, "THROW", CancellationToken.None);
+ await Calls.AsyncUnaryCall(callDetails, "THROW");
Assert.Fail();
}
catch (RpcException e)
@@ -175,8 +180,8 @@ namespace Grpc.Core.Tests
[Test]
public async Task ClientStreamingCall()
{
- var internalCall = new Call<string, string>(ServiceName, ConcatAndEchoMethod, channel, Metadata.Empty);
- var call = Calls.AsyncClientStreamingCall(internalCall, CancellationToken.None);
+ var callDetails = new CallInvocationDetails<string, string>(channel, ConcatAndEchoMethod, new CallOptions());
+ var call = Calls.AsyncClientStreamingCall(callDetails);
await call.RequestStream.WriteAll(new string[] { "A", "B", "C" });
Assert.AreEqual("ABC", await call.ResponseAsync);
@@ -185,10 +190,9 @@ namespace Grpc.Core.Tests
[Test]
public async Task ClientStreamingCall_CancelAfterBegin()
{
- var internalCall = new Call<string, string>(ServiceName, ConcatAndEchoMethod, channel, Metadata.Empty);
-
var cts = new CancellationTokenSource();
- var call = Calls.AsyncClientStreamingCall(internalCall, cts.Token);
+ var callDetails = new CallInvocationDetails<string, string>(channel, ConcatAndEchoMethod, new CallOptions(cancellationToken: cts.Token));
+ var call = Calls.AsyncClientStreamingCall(callDetails);
// TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it.
await Task.Delay(1000);
@@ -212,8 +216,8 @@ namespace Grpc.Core.Tests
new Metadata.Entry("ascii-header", "abcdefg"),
new Metadata.Entry("binary-header-bin", new byte[] { 1, 2, 3, 0, 0xff }),
};
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, headers);
- var call = Calls.AsyncUnaryCall(internalCall, "ABC", CancellationToken.None);
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions(headers: headers));
+ var call = Calls.AsyncUnaryCall(callDetails, "ABC");
Assert.AreEqual("ABC", call.ResponseAsync.Result);
@@ -233,25 +237,25 @@ namespace Grpc.Core.Tests
{
channel.Dispose();
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
- Assert.Throws(typeof(ObjectDisposedException), () => Calls.BlockingUnaryCall(internalCall, "ABC", CancellationToken.None));
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
+ Assert.Throws(typeof(ObjectDisposedException), () => Calls.BlockingUnaryCall(callDetails, "ABC"));
}
[Test]
public void UnaryCallPerformance()
{
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
BenchmarkUtil.RunBenchmark(100, 100,
- () => { Calls.BlockingUnaryCall(internalCall, "ABC", default(CancellationToken)); });
+ () => { Calls.BlockingUnaryCall(callDetails, "ABC"); });
}
[Test]
public void UnknownMethodHandler()
{
- var internalCall = new Call<string, string>(ServiceName, NonexistentMethod, channel, Metadata.Empty);
+ var callDetails = new CallInvocationDetails<string, string>(channel, NonexistentMethod, new CallOptions());
try
{
- Calls.BlockingUnaryCall(internalCall, "ABC", default(CancellationToken));
+ Calls.BlockingUnaryCall(callDetails, "ABC");
Assert.Fail();
}
catch (RpcException e)
@@ -263,16 +267,16 @@ namespace Grpc.Core.Tests
[Test]
public void UserAgentStringPresent()
{
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
- string userAgent = Calls.BlockingUnaryCall(internalCall, "RETURN-USER-AGENT", CancellationToken.None);
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
+ string userAgent = Calls.BlockingUnaryCall(callDetails, "RETURN-USER-AGENT");
Assert.IsTrue(userAgent.StartsWith("grpc-csharp/"));
}
[Test]
public void PeerInfoPresent()
{
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
- string peer = Calls.BlockingUnaryCall(internalCall, "RETURN-PEER", CancellationToken.None);
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
+ string peer = Calls.BlockingUnaryCall(callDetails, "RETURN-PEER");
Assert.IsTrue(peer.Contains(Host));
}
@@ -284,8 +288,8 @@ namespace Grpc.Core.Tests
var stateChangedTask = channel.WaitForStateChangedAsync(channel.State);
- var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, Metadata.Empty);
- await Calls.AsyncUnaryCall(internalCall, "abc", CancellationToken.None);
+ var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
+ await Calls.AsyncUnaryCall(callDetails, "abc");
await stateChangedTask;
Assert.AreEqual(ChannelState.Ready, channel.State);
diff --git a/src/csharp/Grpc.Core.Tests/ServerTest.cs b/src/csharp/Grpc.Core.Tests/ServerTest.cs
index ba9efae871..485006ebac 100644
--- a/src/csharp/Grpc.Core.Tests/ServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ServerTest.cs
@@ -32,6 +32,7 @@
#endregion
using System;
+using System.Linq;
using Grpc.Core;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
@@ -44,11 +45,45 @@ namespace Grpc.Core.Tests
[Test]
public void StartAndShutdownServer()
{
- Server server = new Server();
- server.AddPort("localhost", Server.PickUnusedPort, ServerCredentials.Insecure);
+ Server server = new Server
+ {
+ Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) }
+ };
server.Start();
server.ShutdownAsync().Wait();
GrpcEnvironment.Shutdown();
}
+
+ [Test]
+ public void PickUnusedPort()
+ {
+ Server server = new Server
+ {
+ Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) }
+ };
+
+ var boundPort = server.Ports.Single();
+ Assert.AreEqual(0, boundPort.Port);
+ Assert.Greater(boundPort.BoundPort, 0);
+
+ server.Start();
+ server.ShutdownAsync();
+ GrpcEnvironment.Shutdown();
+ }
+
+ [Test]
+ public void CannotModifyAfterStarted()
+ {
+ Server server = new Server
+ {
+ Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) }
+ };
+ server.Start();
+ Assert.Throws(typeof(InvalidOperationException), () => server.Ports.Add("localhost", 9999, ServerCredentials.Insecure));
+ Assert.Throws(typeof(InvalidOperationException), () => server.Services.Add(ServerServiceDefinition.CreateBuilder("serviceName").Build()));
+
+ server.ShutdownAsync().Wait();
+ GrpcEnvironment.Shutdown();
+ }
}
}
diff --git a/src/csharp/Grpc.Core.Tests/TimeoutsTest.cs b/src/csharp/Grpc.Core.Tests/TimeoutsTest.cs
index a09273b846..fc395b0acd 100644
--- a/src/csharp/Grpc.Core.Tests/TimeoutsTest.cs
+++ b/src/csharp/Grpc.Core.Tests/TimeoutsTest.cs
@@ -49,11 +49,12 @@ namespace Grpc.Core.Tests
public class TimeoutsTest
{
const string Host = "localhost";
- const string ServiceName = "/tests.Test";
+ const string ServiceName = "tests.Test";
static readonly Method<string, string> TestMethod = new Method<string, string>(
MethodType.Unary,
- "/tests.Test/Test",
+ ServiceName,
+ "Test",
Marshallers.StringMarshaller,
Marshallers.StringMarshaller);
@@ -70,11 +71,13 @@ namespace Grpc.Core.Tests
[SetUp]
public void Init()
{
- server = new Server();
- server.AddServiceDefinition(ServiceDefinition);
- int port = server.AddPort(Host, Server.PickUnusedPort, ServerCredentials.Insecure);
+ server = new Server
+ {
+ Services = { ServiceDefinition },
+ Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
+ };
server.Start();
- channel = new Channel(Host, port, Credentials.Insecure);
+ channel = new Channel(Host, server.Ports.Single().BoundPort, Credentials.Insecure);
stringFromServerHandlerTcs = new TaskCompletionSource<string>();
}
@@ -96,12 +99,12 @@ namespace Grpc.Core.Tests
public void InfiniteDeadline()
{
// no deadline specified, check server sees infinite deadline
- var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty);
- Assert.AreEqual("DATETIME_MAXVALUE", Calls.BlockingUnaryCall(internalCall, "RETURN_DEADLINE", CancellationToken.None));
+ var callDetails = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions());
+ Assert.AreEqual("DATETIME_MAXVALUE", Calls.BlockingUnaryCall(callDetails, "RETURN_DEADLINE"));
// DateTime.MaxValue deadline specified, check server sees infinite deadline
- var internalCall2 = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, DateTime.MaxValue);
- Assert.AreEqual("DATETIME_MAXVALUE", Calls.BlockingUnaryCall(internalCall2, "RETURN_DEADLINE", CancellationToken.None));
+ var callDetails2 = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions());
+ Assert.AreEqual("DATETIME_MAXVALUE", Calls.BlockingUnaryCall(callDetails2, "RETURN_DEADLINE"));
}
[Test]
@@ -110,9 +113,9 @@ namespace Grpc.Core.Tests
var remainingTimeClient = TimeSpan.FromDays(7);
var deadline = DateTime.UtcNow + remainingTimeClient;
Thread.Sleep(1000);
- var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline);
+ var callDetails = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions(deadline: deadline));
- var serverDeadlineTicksString = Calls.BlockingUnaryCall(internalCall, "RETURN_DEADLINE", CancellationToken.None);
+ var serverDeadlineTicksString = Calls.BlockingUnaryCall(callDetails, "RETURN_DEADLINE");
var serverDeadline = new DateTime(long.Parse(serverDeadlineTicksString), DateTimeKind.Utc);
// A fairly relaxed check that the deadline set by client and deadline seen by server
@@ -124,12 +127,11 @@ namespace Grpc.Core.Tests
[Test]
public void DeadlineInThePast()
{
- var deadline = DateTime.MinValue;
- var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline);
+ var callDetails = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions(deadline: DateTime.MinValue));
try
{
- Calls.BlockingUnaryCall(internalCall, "TIMEOUT", CancellationToken.None);
+ Calls.BlockingUnaryCall(callDetails, "TIMEOUT");
Assert.Fail();
}
catch (RpcException e)
@@ -143,11 +145,11 @@ namespace Grpc.Core.Tests
public void DeadlineExceededStatusOnTimeout()
{
var deadline = DateTime.UtcNow.Add(TimeSpan.FromSeconds(5));
- var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline);
+ var callDetails = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions(deadline: deadline));
try
{
- Calls.BlockingUnaryCall(internalCall, "TIMEOUT", CancellationToken.None);
+ Calls.BlockingUnaryCall(callDetails, "TIMEOUT");
Assert.Fail();
}
catch (RpcException e)
@@ -161,11 +163,11 @@ namespace Grpc.Core.Tests
public void ServerReceivesCancellationOnTimeout()
{
var deadline = DateTime.UtcNow.Add(TimeSpan.FromSeconds(5));
- var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline);
+ var callDetails = new CallInvocationDetails<string, string>(channel, TestMethod, new CallOptions(deadline: deadline));
try
{
- Calls.BlockingUnaryCall(internalCall, "CHECK_CANCELLATION_RECEIVED", CancellationToken.None);
+ Calls.BlockingUnaryCall(callDetails, "CHECK_CANCELLATION_RECEIVED");
Assert.Fail();
}
catch (RpcException e)
diff --git a/src/csharp/Grpc.Core/Call.cs b/src/csharp/Grpc.Core/CallInvocationDetails.cs
index 94c5e26082..eb23a3a209 100644
--- a/src/csharp/Grpc.Core/Call.cs
+++ b/src/csharp/Grpc.Core/CallInvocationDetails.cs
@@ -38,30 +38,30 @@ using Grpc.Core.Utils;
namespace Grpc.Core
{
/// <summary>
- /// Abstraction of a call to be invoked on a client.
+ /// Details about a client-side call to be invoked.
/// </summary>
- public class Call<TRequest, TResponse>
+ public class CallInvocationDetails<TRequest, TResponse>
{
- readonly string name;
+ readonly Channel channel;
+ readonly string method;
+ readonly string host;
readonly Marshaller<TRequest> requestMarshaller;
readonly Marshaller<TResponse> responseMarshaller;
- readonly Channel channel;
- readonly Metadata headers;
- readonly DateTime deadline;
+ readonly CallOptions options;
- public Call(string serviceName, Method<TRequest, TResponse> method, Channel channel, Metadata headers)
- : this(serviceName, method, channel, headers, DateTime.MaxValue)
+ public CallInvocationDetails(Channel channel, Method<TRequest, TResponse> method, CallOptions options) :
+ this(channel, method.FullName, null, method.RequestMarshaller, method.ResponseMarshaller, options)
{
}
- public Call(string serviceName, Method<TRequest, TResponse> method, Channel channel, Metadata headers, DateTime deadline)
+ public CallInvocationDetails(Channel channel, string method, string host, Marshaller<TRequest> requestMarshaller, Marshaller<TResponse> responseMarshaller, CallOptions options)
{
- this.name = method.GetFullName(serviceName);
- this.requestMarshaller = method.RequestMarshaller;
- this.responseMarshaller = method.ResponseMarshaller;
this.channel = Preconditions.CheckNotNull(channel);
- this.headers = Preconditions.CheckNotNull(headers);
- this.deadline = deadline;
+ this.method = Preconditions.CheckNotNull(method);
+ this.host = host;
+ this.requestMarshaller = Preconditions.CheckNotNull(requestMarshaller);
+ this.responseMarshaller = Preconditions.CheckNotNull(responseMarshaller);
+ this.options = Preconditions.CheckNotNull(options);
}
public Channel Channel
@@ -72,49 +72,43 @@ namespace Grpc.Core
}
}
- /// <summary>
- /// Full methods name including the service name.
- /// </summary>
- public string Name
+ public string Method
{
get
{
- return name;
+ return this.method;
}
}
- /// <summary>
- /// Headers to send at the beginning of the call.
- /// </summary>
- public Metadata Headers
+ public string Host
{
get
{
- return headers;
+ return this.host;
}
}
- public DateTime Deadline
+ public Marshaller<TRequest> RequestMarshaller
{
get
{
- return this.deadline;
+ return this.requestMarshaller;
}
}
- public Marshaller<TRequest> RequestMarshaller
+ public Marshaller<TResponse> ResponseMarshaller
{
get
{
- return requestMarshaller;
+ return this.responseMarshaller;
}
}
-
- public Marshaller<TResponse> ResponseMarshaller
+
+ public CallOptions Options
{
get
{
- return responseMarshaller;
+ return options;
}
}
}
diff --git a/src/csharp/Grpc.Core/CallOptions.cs b/src/csharp/Grpc.Core/CallOptions.cs
new file mode 100644
index 0000000000..8e9739335f
--- /dev/null
+++ b/src/csharp/Grpc.Core/CallOptions.cs
@@ -0,0 +1,89 @@
+#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.Threading;
+
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core
+{
+ /// <summary>
+ /// Options for calls made by client.
+ /// </summary>
+ public class CallOptions
+ {
+ readonly Metadata headers;
+ readonly DateTime deadline;
+ readonly CancellationToken cancellationToken;
+
+ /// <summary>
+ /// Creates a new instance of <c>CallOptions</c>.
+ /// </summary>
+ /// <param name="headers">Headers to be sent with the call.</param>
+ /// <param name="deadline">Deadline for the call to finish. null means no deadline.</param>
+ /// <param name="cancellationToken">Can be used to request cancellation of the call.</param>
+ public CallOptions(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ // TODO(jtattermusch): consider only creating metadata object once it's really needed.
+ this.headers = headers != null ? headers : new Metadata();
+ this.deadline = deadline.HasValue ? deadline.Value : DateTime.MaxValue;
+ this.cancellationToken = cancellationToken;
+ }
+
+ /// <summary>
+ /// Headers to send at the beginning of the call.
+ /// </summary>
+ public Metadata Headers
+ {
+ get { return headers; }
+ }
+
+ /// <summary>
+ /// Call deadline.
+ /// </summary>
+ public DateTime Deadline
+ {
+ get { return deadline; }
+ }
+
+ /// <summary>
+ /// Token that can be used for cancelling the call.
+ /// </summary>
+ public CancellationToken CancellationToken
+ {
+ get { return cancellationToken; }
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/Calls.cs b/src/csharp/Grpc.Core/Calls.cs
index 054fc27491..00a8cabf82 100644
--- a/src/csharp/Grpc.Core/Calls.cs
+++ b/src/csharp/Grpc.Core/Calls.cs
@@ -43,70 +43,52 @@ namespace Grpc.Core
/// </summary>
public static class Calls
{
- public static TResponse BlockingUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
+ public static TResponse BlockingUnaryCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call, TRequest req)
where TRequest : class
where TResponse : class
{
- var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
- // TODO(jtattermusch): this gives a race that cancellation can be requested before the call even starts.
- RegisterCancellationCallback(asyncCall, token);
- return asyncCall.UnaryCall(call.Channel, call.Name, req, call.Headers, call.Deadline);
+ var asyncCall = new AsyncCall<TRequest, TResponse>(call);
+ return asyncCall.UnaryCall(req);
}
- public static AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
+ public static AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call, TRequest req)
where TRequest : class
where TResponse : class
{
- var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
- asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline));
- var asyncResult = asyncCall.UnaryCallAsync(req, call.Headers, call.Deadline);
- RegisterCancellationCallback(asyncCall, token);
+ var asyncCall = new AsyncCall<TRequest, TResponse>(call);
+ var asyncResult = asyncCall.UnaryCallAsync(req);
return new AsyncUnaryCall<TResponse>(asyncResult, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel);
}
- public static AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
+ public static AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call, TRequest req)
where TRequest : class
where TResponse : class
{
- var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
- asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline));
- asyncCall.StartServerStreamingCall(req, call.Headers, call.Deadline);
- RegisterCancellationCallback(asyncCall, token);
+ var asyncCall = new AsyncCall<TRequest, TResponse>(call);
+ asyncCall.StartServerStreamingCall(req);
var responseStream = new ClientResponseStream<TRequest, TResponse>(asyncCall);
return new AsyncServerStreamingCall<TResponse>(responseStream, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel);
}
- public static AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, CancellationToken token)
+ public static AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call)
where TRequest : class
where TResponse : class
{
- var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
- asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline));
- var resultTask = asyncCall.ClientStreamingCallAsync(call.Headers, call.Deadline);
- RegisterCancellationCallback(asyncCall, token);
+ var asyncCall = new AsyncCall<TRequest, TResponse>(call);
+ var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall);
return new AsyncClientStreamingCall<TRequest, TResponse>(requestStream, resultTask, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel);
}
- public static AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, CancellationToken token)
+ public static AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(CallInvocationDetails<TRequest, TResponse> call)
where TRequest : class
where TResponse : class
{
- var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
- asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline));
- asyncCall.StartDuplexStreamingCall(call.Headers, call.Deadline);
- RegisterCancellationCallback(asyncCall, token);
+ var asyncCall = new AsyncCall<TRequest, TResponse>(call);
+ asyncCall.StartDuplexStreamingCall();
var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall);
var responseStream = new ClientResponseStream<TRequest, TResponse>(asyncCall);
return new AsyncDuplexStreamingCall<TRequest, TResponse>(requestStream, responseStream, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel);
}
-
- private static void RegisterCancellationCallback<TRequest, TResponse>(AsyncCall<TRequest, TResponse> asyncCall, CancellationToken token)
- {
- if (token.CanBeCanceled)
- {
- token.Register(() => asyncCall.Cancel());
- }
- }
}
}
diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs
index 0b69610443..9273ea4582 100644
--- a/src/csharp/Grpc.Core/Channel.cs
+++ b/src/csharp/Grpc.Core/Channel.cs
@@ -178,22 +178,6 @@ namespace Grpc.Core
}
}
- internal CompletionQueueSafeHandle CompletionQueue
- {
- get
- {
- return this.environment.CompletionQueue;
- }
- }
-
- internal CompletionRegistry CompletionRegistry
- {
- get
- {
- return this.environment.CompletionRegistry;
- }
- }
-
internal GrpcEnvironment Environment
{
get
diff --git a/src/csharp/Grpc.Core/ChannelOptions.cs b/src/csharp/Grpc.Core/ChannelOptions.cs
index f70408dae7..1e0f90287a 100644
--- a/src/csharp/Grpc.Core/ChannelOptions.cs
+++ b/src/csharp/Grpc.Core/ChannelOptions.cs
@@ -30,7 +30,6 @@
#endregion
using System;
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
diff --git a/src/csharp/Grpc.Core/ClientBase.cs b/src/csharp/Grpc.Core/ClientBase.cs
index fd3473128a..88494bb4ac 100644
--- a/src/csharp/Grpc.Core/ClientBase.cs
+++ b/src/csharp/Grpc.Core/ClientBase.cs
@@ -76,19 +76,17 @@ namespace Grpc.Core
/// <summary>
/// Creates a new call to given method.
/// </summary>
- protected Call<TRequest, TResponse> CreateCall<TRequest, TResponse>(string serviceName, Method<TRequest, TResponse> method, Metadata metadata, DateTime? deadline)
+ protected CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, CallOptions options)
where TRequest : class
where TResponse : class
{
var interceptor = HeaderInterceptor;
if (interceptor != null)
{
- metadata = metadata ?? new Metadata();
- interceptor(metadata);
- metadata.Freeze();
+ interceptor(options.Headers);
+ options.Headers.Freeze();
}
- return new Call<TRequest, TResponse>(serviceName, method, channel,
- metadata ?? Metadata.Empty, deadline ?? DateTime.MaxValue);
+ return new CallInvocationDetails<TRequest, TResponse>(channel, method, options);
}
}
}
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 641b54baba..52defd1965 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -44,9 +44,6 @@
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
- <Reference Include="System.Collections.Immutable">
- <HintPath>..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
- </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AsyncDuplexStreamingCall.cs" />
@@ -55,11 +52,11 @@
<Compile Include="IServerStreamWriter.cs" />
<Compile Include="IAsyncStreamWriter.cs" />
<Compile Include="IAsyncStreamReader.cs" />
+ <Compile Include="ServerPort.cs" />
<Compile Include="Version.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RpcException.cs" />
<Compile Include="Calls.cs" />
- <Compile Include="Call.cs" />
<Compile Include="AsyncClientStreamingCall.cs" />
<Compile Include="GrpcEnvironment.cs" />
<Compile Include="Status.cs" />
@@ -116,6 +113,8 @@
<Compile Include="Logging\ConsoleLogger.cs" />
<Compile Include="Internal\NativeLogRedirector.cs" />
<Compile Include="ChannelState.cs" />
+ <Compile Include="CallInvocationDetails.cs" />
+ <Compile Include="CallOptions.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Grpc.Core.nuspec" />
@@ -146,7 +145,5 @@
</Target>
<Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" />
<Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" />
- <ItemGroup>
- <Folder Include="Logging\" />
- </ItemGroup>
+ <ItemGroup />
</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec
index 086776f69d..fe49efc7ec 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.nuspec
+++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec
@@ -15,7 +15,6 @@
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
<dependencies>
- <dependency id="System.Collections.Immutable" version="1.1.36" />
<dependency id="Ix-Async" version="1.2.3" />
<dependency id="grpc.native.csharp_ext" version="$GrpcNativeCsharpExtVersion$" />
</dependencies>
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index 48f466460f..414b5c4282 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -50,7 +50,7 @@ namespace Grpc.Core.Internal
{
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<AsyncCall<TRequest, TResponse>>();
- Channel channel;
+ readonly CallInvocationDetails<TRequest, TResponse> callDetails;
// Completion of a pending unary response if not null.
TaskCompletionSource<TResponse> unaryResponseTcs;
@@ -60,26 +60,18 @@ namespace Grpc.Core.Internal
bool readObserverCompleted; // True if readObserver has already been completed.
- public AsyncCall(Func<TRequest, byte[]> serializer, Func<byte[], TResponse> deserializer) : base(serializer, deserializer)
+ public AsyncCall(CallInvocationDetails<TRequest, TResponse> callDetails)
+ : base(callDetails.RequestMarshaller.Serializer, callDetails.ResponseMarshaller.Deserializer)
{
- }
-
- public void Initialize(Channel channel, CompletionQueueSafeHandle cq, string methodName, Timespec deadline)
- {
- this.channel = channel;
- var call = channel.Handle.CreateCall(channel.CompletionRegistry, cq, methodName, null, deadline);
- channel.Environment.DebugStats.ActiveClientCalls.Increment();
- InitializeInternal(call);
+ this.callDetails = callDetails;
}
// TODO: this method is not Async, so it shouldn't be in AsyncCall class, but
// it is reusing fair amount of code in this class, so we are leaving it here.
- // TODO: for other calls, you need to call Initialize, this methods calls initialize
- // on its own, so there's a usage inconsistency.
/// <summary>
/// Blocking unary request - unary response call.
/// </summary>
- public TResponse UnaryCall(Channel channel, string methodName, TRequest msg, Metadata headers, DateTime deadline)
+ public TResponse UnaryCall(TRequest msg)
{
using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create())
{
@@ -89,13 +81,15 @@ namespace Grpc.Core.Internal
lock (myLock)
{
- Initialize(channel, cq, methodName, Timespec.FromDateTime(deadline));
+ Preconditions.CheckState(!started);
started = true;
+ Initialize(cq);
+
halfcloseRequested = true;
readingDone = true;
}
- using (var metadataArray = MetadataArraySafeHandle.Create(headers))
+ using (var metadataArray = MetadataArraySafeHandle.Create(callDetails.Options.Headers))
{
using (var ctx = BatchContextSafeHandle.Create())
{
@@ -129,20 +123,22 @@ namespace Grpc.Core.Internal
/// <summary>
/// Starts a unary request - unary response call.
/// </summary>
- public Task<TResponse> UnaryCallAsync(TRequest msg, Metadata headers, DateTime deadline)
+ public Task<TResponse> UnaryCallAsync(TRequest msg)
{
lock (myLock)
{
- Preconditions.CheckNotNull(call);
-
+ Preconditions.CheckState(!started);
started = true;
+
+ Initialize(callDetails.Channel.Environment.CompletionQueue);
+
halfcloseRequested = true;
readingDone = true;
byte[] payload = UnsafeSerialize(msg);
unaryResponseTcs = new TaskCompletionSource<TResponse>();
- using (var metadataArray = MetadataArraySafeHandle.Create(headers))
+ using (var metadataArray = MetadataArraySafeHandle.Create(callDetails.Options.Headers))
{
call.StartUnary(payload, HandleUnaryResponse, metadataArray);
}
@@ -154,17 +150,19 @@ namespace Grpc.Core.Internal
/// Starts a streamed request - unary response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary>
- public Task<TResponse> ClientStreamingCallAsync(Metadata headers, DateTime deadline)
+ public Task<TResponse> ClientStreamingCallAsync()
{
lock (myLock)
{
- Preconditions.CheckNotNull(call);
-
+ Preconditions.CheckState(!started);
started = true;
+
+ Initialize(callDetails.Channel.Environment.CompletionQueue);
+
readingDone = true;
unaryResponseTcs = new TaskCompletionSource<TResponse>();
- using (var metadataArray = MetadataArraySafeHandle.Create(headers))
+ using (var metadataArray = MetadataArraySafeHandle.Create(callDetails.Options.Headers))
{
call.StartClientStreaming(HandleUnaryResponse, metadataArray);
}
@@ -176,19 +174,21 @@ namespace Grpc.Core.Internal
/// <summary>
/// Starts a unary request - streamed response call.
/// </summary>
- public void StartServerStreamingCall(TRequest msg, Metadata headers, DateTime deadline)
+ public void StartServerStreamingCall(TRequest msg)
{
lock (myLock)
{
- Preconditions.CheckNotNull(call);
-
+ Preconditions.CheckState(!started);
started = true;
+
+ Initialize(callDetails.Channel.Environment.CompletionQueue);
+
halfcloseRequested = true;
halfclosed = true; // halfclose not confirmed yet, but it will be once finishedHandler is called.
byte[] payload = UnsafeSerialize(msg);
- using (var metadataArray = MetadataArraySafeHandle.Create(headers))
+ using (var metadataArray = MetadataArraySafeHandle.Create(callDetails.Options.Headers))
{
call.StartServerStreaming(payload, HandleFinished, metadataArray);
}
@@ -199,15 +199,16 @@ namespace Grpc.Core.Internal
/// Starts a streaming request - streaming response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary>
- public void StartDuplexStreamingCall(Metadata headers, DateTime deadline)
+ public void StartDuplexStreamingCall()
{
lock (myLock)
{
- Preconditions.CheckNotNull(call);
-
+ Preconditions.CheckState(!started);
started = true;
- using (var metadataArray = MetadataArraySafeHandle.Create(headers))
+ Initialize(callDetails.Channel.Environment.CompletionQueue);
+
+ using (var metadataArray = MetadataArraySafeHandle.Create(callDetails.Options.Headers))
{
call.StartDuplexStreaming(HandleFinished, metadataArray);
}
@@ -309,7 +310,26 @@ namespace Grpc.Core.Internal
protected override void OnReleaseResources()
{
- channel.Environment.DebugStats.ActiveClientCalls.Decrement();
+ callDetails.Channel.Environment.DebugStats.ActiveClientCalls.Decrement();
+ }
+
+ private void Initialize(CompletionQueueSafeHandle cq)
+ {
+ var call = callDetails.Channel.Handle.CreateCall(callDetails.Channel.Environment.CompletionRegistry, cq,
+ callDetails.Method, callDetails.Host, Timespec.FromDateTime(callDetails.Options.Deadline));
+ callDetails.Channel.Environment.DebugStats.ActiveClientCalls.Increment();
+ InitializeInternal(call);
+ RegisterCancellationCallback();
+ }
+
+ // Make sure that once cancellationToken for this call is cancelled, Cancel() will be called.
+ private void RegisterCancellationCallback()
+ {
+ var token = callDetails.Options.CancellationToken;
+ if (token.CanBeCanceled)
+ {
+ token.Register(() => this.Cancel());
+ }
}
/// <summary>
diff --git a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
index 59238a452c..37a4f5256b 100644
--- a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
@@ -42,7 +42,7 @@ namespace Grpc.Core.Internal
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);
+ static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, bool forceClientAuth);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_server_credentials_release(IntPtr credentials);
@@ -51,12 +51,13 @@ namespace Grpc.Core.Internal
{
}
- public static ServerCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray)
+ public static ServerCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, bool forceClientAuth)
{
Preconditions.CheckArgument(keyCertPairCertChainArray.Length == keyCertPairPrivateKeyArray.Length);
return grpcsharp_ssl_server_credentials_create(pemRootCerts,
keyCertPairCertChainArray, keyCertPairPrivateKeyArray,
- new UIntPtr((ulong)keyCertPairCertChainArray.Length));
+ new UIntPtr((ulong)keyCertPairCertChainArray.Length),
+ forceClientAuth);
}
protected override bool ReleaseHandle()
diff --git a/src/csharp/Grpc.Core/KeyCertificatePair.cs b/src/csharp/Grpc.Core/KeyCertificatePair.cs
index 7cea18618e..5def15a656 100644
--- a/src/csharp/Grpc.Core/KeyCertificatePair.cs
+++ b/src/csharp/Grpc.Core/KeyCertificatePair.cs
@@ -33,7 +33,6 @@
using System;
using System.Collections.Generic;
-using System.Collections.Immutable;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core/Metadata.cs
index 2f308cbb11..6fd0a7109d 100644
--- a/src/csharp/Grpc.Core/Metadata.cs
+++ b/src/csharp/Grpc.Core/Metadata.cs
@@ -32,7 +32,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using System.Text;
diff --git a/src/csharp/Grpc.Core/Method.cs b/src/csharp/Grpc.Core/Method.cs
index 77d36191c3..cc047ac9f8 100644
--- a/src/csharp/Grpc.Core/Method.cs
+++ b/src/csharp/Grpc.Core/Method.cs
@@ -53,16 +53,20 @@ namespace Grpc.Core
public class Method<TRequest, TResponse>
{
readonly MethodType type;
+ readonly string serviceName;
readonly string name;
readonly Marshaller<TRequest> requestMarshaller;
readonly Marshaller<TResponse> responseMarshaller;
+ readonly string fullName;
- public Method(MethodType type, string name, Marshaller<TRequest> requestMarshaller, Marshaller<TResponse> responseMarshaller)
+ public Method(MethodType type, string serviceName, string name, Marshaller<TRequest> requestMarshaller, Marshaller<TResponse> responseMarshaller)
{
this.type = type;
- this.name = name;
- this.requestMarshaller = requestMarshaller;
- this.responseMarshaller = responseMarshaller;
+ this.serviceName = Preconditions.CheckNotNull(serviceName);
+ this.name = Preconditions.CheckNotNull(name);
+ this.requestMarshaller = Preconditions.CheckNotNull(requestMarshaller);
+ this.responseMarshaller = Preconditions.CheckNotNull(responseMarshaller);
+ this.fullName = GetFullName(serviceName);
}
public MethodType Type
@@ -72,6 +76,14 @@ namespace Grpc.Core
return this.type;
}
}
+
+ public string ServiceName
+ {
+ get
+ {
+ return this.serviceName;
+ }
+ }
public string Name
{
@@ -97,6 +109,14 @@ namespace Grpc.Core
}
}
+ public string FullName
+ {
+ get
+ {
+ return this.fullName;
+ }
+ }
+
/// <summary>
/// Gets full name of the method including the service name.
/// </summary>
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index 3217547cc4..eb5b043d1c 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -32,7 +32,7 @@
#endregion
using System;
-using System.Collections.Concurrent;
+using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
@@ -48,18 +48,17 @@ namespace Grpc.Core
/// </summary>
public class Server
{
- /// <summary>
- /// Pass this value as port to have the server choose an unused listening port for you.
- /// </summary>
- public const int PickUnusedPort = 0;
-
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<Server>();
+ readonly ServiceDefinitionCollection serviceDefinitions;
+ readonly ServerPortCollection ports;
readonly GrpcEnvironment environment;
readonly List<ChannelOption> options;
readonly ServerSafeHandle handle;
readonly object myLock = new object();
+ readonly List<ServerServiceDefinition> serviceDefinitionsList = new List<ServerServiceDefinition>();
+ readonly List<ServerPort> serverPortList = new List<ServerPort>();
readonly Dictionary<string, IServerCallHandler> callHandlers = new Dictionary<string, IServerCallHandler>();
readonly TaskCompletionSource<object> shutdownTcs = new TaskCompletionSource<object>();
@@ -72,6 +71,8 @@ namespace Grpc.Core
/// <param name="options">Channel options.</param>
public Server(IEnumerable<ChannelOption> options = null)
{
+ this.serviceDefinitions = new ServiceDefinitionCollection(this);
+ this.ports = new ServerPortCollection(this);
this.environment = GrpcEnvironment.GetInstance();
this.options = options != null ? new List<ChannelOption>(options) : new List<ChannelOption>();
using (var channelArgs = ChannelOptions.CreateChannelArgs(this.options))
@@ -81,47 +82,26 @@ namespace Grpc.Core
}
/// <summary>
- /// Adds a service definition to the server. This is how you register
- /// handlers for a service with the server.
- /// Only call this before Start().
+ /// Services that will be exported by the server once started. Register a service with this
+ /// server by adding its definition to this collection.
/// </summary>
- public void AddServiceDefinition(ServerServiceDefinition serviceDefinition)
+ public ServiceDefinitionCollection Services
{
- lock (myLock)
+ get
{
- Preconditions.CheckState(!startRequested);
- foreach (var entry in serviceDefinition.CallHandlers)
- {
- callHandlers.Add(entry.Key, entry.Value);
- }
+ return serviceDefinitions;
}
}
/// <summary>
- /// Add a port on which server should listen.
- /// Only call this before Start().
+ /// Ports on which the server will listen once started. Register a port with this
+ /// server by adding its definition to this collection.
/// </summary>
- /// <returns>The port on which server will be listening.</returns>
- /// <param name="host">the host</param>
- /// <param name="port">the port. If zero, an unused port is chosen automatically.</param>
- public int AddPort(string host, int port, ServerCredentials credentials)
+ public ServerPortCollection Ports
{
- lock (myLock)
+ get
{
- Preconditions.CheckNotNull(credentials);
- Preconditions.CheckState(!startRequested);
- var address = string.Format("{0}:{1}", host, port);
- using (var nativeCredentials = credentials.ToNativeCredentials())
- {
- if (nativeCredentials != null)
- {
- return handle.AddSecurePort(address, nativeCredentials);
- }
- else
- {
- return handle.AddInsecurePort(address);
- }
- }
+ return ports;
}
}
@@ -190,6 +170,50 @@ namespace Grpc.Core
}
/// <summary>
+ /// Adds a service definition.
+ /// </summary>
+ private void AddServiceDefinitionInternal(ServerServiceDefinition serviceDefinition)
+ {
+ lock (myLock)
+ {
+ Preconditions.CheckState(!startRequested);
+ foreach (var entry in serviceDefinition.CallHandlers)
+ {
+ callHandlers.Add(entry.Key, entry.Value);
+ }
+ serviceDefinitionsList.Add(serviceDefinition);
+ }
+ }
+
+ /// <summary>
+ /// Adds a listening port.
+ /// </summary>
+ private int AddPortInternal(ServerPort serverPort)
+ {
+ lock (myLock)
+ {
+ Preconditions.CheckNotNull(serverPort.Credentials);
+ Preconditions.CheckState(!startRequested);
+ var address = string.Format("{0}:{1}", serverPort.Host, serverPort.Port);
+ int boundPort;
+ using (var nativeCredentials = serverPort.Credentials.ToNativeCredentials())
+ {
+ if (nativeCredentials != null)
+ {
+ boundPort = handle.AddSecurePort(address, nativeCredentials);
+ }
+ else
+ {
+ boundPort = handle.AddInsecurePort(address);
+ }
+ }
+ var newServerPort = new ServerPort(serverPort, boundPort);
+ this.serverPortList.Add(newServerPort);
+ return boundPort;
+ }
+ }
+
+ /// <summary>
/// Allows one new RPC call to be received by server.
/// </summary>
private void AllowOneRpc()
@@ -249,5 +273,82 @@ namespace Grpc.Core
{
shutdownTcs.SetResult(null);
}
+
+ /// <summary>
+ /// Collection of service definitions.
+ /// </summary>
+ public class ServiceDefinitionCollection : IEnumerable<ServerServiceDefinition>
+ {
+ readonly Server server;
+
+ internal ServiceDefinitionCollection(Server server)
+ {
+ this.server = server;
+ }
+
+ /// <summary>
+ /// Adds a service definition to the server. This is how you register
+ /// handlers for a service with the server. Only call this before Start().
+ /// </summary>
+ public void Add(ServerServiceDefinition serviceDefinition)
+ {
+ server.AddServiceDefinitionInternal(serviceDefinition);
+ }
+
+ public IEnumerator<ServerServiceDefinition> GetEnumerator()
+ {
+ return server.serviceDefinitionsList.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return server.serviceDefinitionsList.GetEnumerator();
+ }
+ }
+
+ /// <summary>
+ /// Collection of server ports.
+ /// </summary>
+ public class ServerPortCollection : IEnumerable<ServerPort>
+ {
+ readonly Server server;
+
+ internal ServerPortCollection(Server server)
+ {
+ this.server = server;
+ }
+
+ /// <summary>
+ /// Adds a new port on which server should listen.
+ /// Only call this before Start().
+ /// <returns>The port on which server will be listening.</returns>
+ /// </summary>
+ public int Add(ServerPort serverPort)
+ {
+ return server.AddPortInternal(serverPort);
+ }
+
+ /// <summary>
+ /// Adds a new port on which server should listen.
+ /// <returns>The port on which server will be listening.</returns>
+ /// </summary>
+ /// <param name="host">the host</param>
+ /// <param name="port">the port. If zero, an unused port is chosen automatically.</param>
+ /// <param name="credentials">credentials to use to secure this port.</param>
+ public int Add(string host, int port, ServerCredentials credentials)
+ {
+ return Add(new ServerPort(host, port, credentials));
+ }
+
+ public IEnumerator<ServerPort> GetEnumerator()
+ {
+ return server.serverPortList.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return server.serverPortList.GetEnumerator();
+ }
+ }
}
}
diff --git a/src/csharp/Grpc.Core/ServerCallContext.cs b/src/csharp/Grpc.Core/ServerCallContext.cs
index 0c48adaea5..032b1390db 100644
--- a/src/csharp/Grpc.Core/ServerCallContext.cs
+++ b/src/csharp/Grpc.Core/ServerCallContext.cs
@@ -65,7 +65,7 @@ namespace Grpc.Core
this.cancellationToken = cancellationToken;
}
- /// <summary> Name of method called in this RPC. </summary>
+ /// <summary>Name of method called in this RPC.</summary>
public string Method
{
get
@@ -74,7 +74,7 @@ namespace Grpc.Core
}
}
- /// <summary> Name of host called in this RPC. </summary>
+ /// <summary>Name of host called in this RPC.</summary>
public string Host
{
get
@@ -83,7 +83,7 @@ namespace Grpc.Core
}
}
- /// <summary> Address of the remote endpoint in URI format. </summary>
+ /// <summary>Address of the remote endpoint in URI format.</summary>
public string Peer
{
get
@@ -92,7 +92,7 @@ namespace Grpc.Core
}
}
- /// <summary> Deadline for this RPC. </summary>
+ /// <summary>Deadline for this RPC.</summary>
public DateTime Deadline
{
get
@@ -101,7 +101,7 @@ namespace Grpc.Core
}
}
- /// <summary> Initial metadata sent by client. </summary>
+ /// <summary>Initial metadata sent by client.</summary>
public Metadata RequestHeaders
{
get
@@ -110,8 +110,7 @@ namespace Grpc.Core
}
}
- // TODO(jtattermusch): support signalling cancellation.
- /// <summary> Cancellation token signals when call is cancelled. </summary>
+ ///<summary>Cancellation token signals when call is cancelled.</summary>
public CancellationToken CancellationToken
{
get
@@ -120,7 +119,7 @@ namespace Grpc.Core
}
}
- /// <summary> Trailers to send back to client after RPC finishes.</summary>
+ /// <summary>Trailers to send back to client after RPC finishes.</summary>
public Metadata ResponseTrailers
{
get
diff --git a/src/csharp/Grpc.Core/ServerCredentials.cs b/src/csharp/Grpc.Core/ServerCredentials.cs
index 32ed4b78a1..c11a1ede08 100644
--- a/src/csharp/Grpc.Core/ServerCredentials.cs
+++ b/src/csharp/Grpc.Core/ServerCredentials.cs
@@ -33,7 +33,6 @@
using System;
using System.Collections.Generic;
-using System.Collections.Immutable;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
@@ -80,18 +79,26 @@ namespace Grpc.Core
{
readonly IList<KeyCertificatePair> keyCertificatePairs;
readonly string rootCertificates;
+ readonly bool forceClientAuth;
/// <summary>
/// Creates server-side SSL credentials.
/// </summary>
- /// <param name="rootCertificates">PEM encoded client root certificates used to authenticate client.</param>
/// <param name="keyCertificatePairs">Key-certificates to use.</param>
- public SslServerCredentials(IEnumerable<KeyCertificatePair> keyCertificatePairs, string rootCertificates)
+ /// <param name="rootCertificates">PEM encoded client root certificates used to authenticate client.</param>
+ /// <param name="forceClientAuth">If true, client will be rejected unless it proves its unthenticity using against rootCertificates.</param>
+ public SslServerCredentials(IEnumerable<KeyCertificatePair> keyCertificatePairs, string rootCertificates, bool forceClientAuth)
{
this.keyCertificatePairs = new List<KeyCertificatePair>(keyCertificatePairs).AsReadOnly();
Preconditions.CheckArgument(this.keyCertificatePairs.Count > 0,
"At least one KeyCertificatePair needs to be provided");
+ if (forceClientAuth)
+ {
+ Preconditions.CheckNotNull(rootCertificates,
+ "Cannot force client authentication unless you provide rootCertificates.");
+ }
this.rootCertificates = rootCertificates;
+ this.forceClientAuth = forceClientAuth;
}
/// <summary>
@@ -100,7 +107,7 @@ namespace Grpc.Core
/// using client root certificates.
/// </summary>
/// <param name="keyCertificatePairs">Key-certificates to use.</param>
- public SslServerCredentials(IEnumerable<KeyCertificatePair> keyCertificatePairs) : this(keyCertificatePairs, null)
+ public SslServerCredentials(IEnumerable<KeyCertificatePair> keyCertificatePairs) : this(keyCertificatePairs, null, false)
{
}
@@ -126,6 +133,17 @@ namespace Grpc.Core
}
}
+ /// <summary>
+ /// If true, the authenticity of client check will be enforced.
+ /// </summary>
+ public bool ForceClientAuthentication
+ {
+ get
+ {
+ return this.forceClientAuth;
+ }
+ }
+
internal override ServerCredentialsSafeHandle ToNativeCredentials()
{
int count = keyCertificatePairs.Count;
@@ -136,7 +154,7 @@ namespace Grpc.Core
certChains[i] = keyCertificatePairs[i].CertificateChain;
keys[i] = keyCertificatePairs[i].PrivateKey;
}
- return ServerCredentialsSafeHandle.CreateSslCredentials(rootCertificates, certChains, keys);
+ return ServerCredentialsSafeHandle.CreateSslCredentials(rootCertificates, certChains, keys, forceClientAuth);
}
}
}
diff --git a/src/csharp/Grpc.Core/ServerPort.cs b/src/csharp/Grpc.Core/ServerPort.cs
new file mode 100644
index 0000000000..55e4bd0062
--- /dev/null
+++ b/src/csharp/Grpc.Core/ServerPort.cs
@@ -0,0 +1,120 @@
+#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.Utils;
+
+namespace Grpc.Core
+{
+ /// <summary>
+ /// A port exposed by a server.
+ /// </summary>
+ public class ServerPort
+ {
+ /// <summary>
+ /// Pass this value as port to have the server choose an unused listening port for you.
+ /// Ports added to a server will contain the bound port in their <see cref="BoundPort"/> property.
+ /// </summary>
+ public const int PickUnused = 0;
+
+ readonly string host;
+ readonly int port;
+ readonly ServerCredentials credentials;
+ readonly int boundPort;
+
+ /// <summary>
+ /// Creates a new port on which server should listen.
+ /// </summary>
+ /// <returns>The port on which server will be listening.</returns>
+ /// <param name="host">the host</param>
+ /// <param name="port">the port. If zero, an unused port is chosen automatically.</param>
+ /// <param name="credentials">credentials to use to secure this port.</param>
+ public ServerPort(string host, int port, ServerCredentials credentials)
+ {
+ this.host = Preconditions.CheckNotNull(host);
+ this.port = port;
+ this.credentials = Preconditions.CheckNotNull(credentials);
+ }
+
+ /// <summary>
+ /// Creates a port from an existing <c>ServerPort</c> instance and boundPort value.
+ /// </summary>
+ internal ServerPort(ServerPort serverPort, int boundPort)
+ {
+ this.host = serverPort.host;
+ this.port = serverPort.port;
+ this.credentials = serverPort.credentials;
+ this.boundPort = boundPort;
+ }
+
+ /// <value>The host.</value>
+ public string Host
+ {
+ get
+ {
+ return host;
+ }
+ }
+
+ /// <value>The port.</value>
+ public int Port
+ {
+ get
+ {
+ return port;
+ }
+ }
+
+ /// <value>The server credentials.</value>
+ public ServerCredentials Credentials
+ {
+ get
+ {
+ return credentials;
+ }
+ }
+
+ /// <value>
+ /// The port actually bound by the server. This is useful if you let server
+ /// pick port automatically. <see cref="PickUnused"/>
+ /// </value>
+ public int BoundPort
+ {
+ get
+ {
+ return boundPort;
+ }
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/ServerServiceDefinition.cs b/src/csharp/Grpc.Core/ServerServiceDefinition.cs
index b180186c12..a00d156e52 100644
--- a/src/csharp/Grpc.Core/ServerServiceDefinition.cs
+++ b/src/csharp/Grpc.Core/ServerServiceDefinition.cs
@@ -33,7 +33,7 @@
using System;
using System.Collections.Generic;
-using System.Collections.Immutable;
+using System.Collections.ObjectModel;
using Grpc.Core.Internal;
namespace Grpc.Core
@@ -43,14 +43,14 @@ namespace Grpc.Core
/// </summary>
public class ServerServiceDefinition
{
- readonly ImmutableDictionary<string, IServerCallHandler> callHandlers;
+ readonly ReadOnlyDictionary<string, IServerCallHandler> callHandlers;
- private ServerServiceDefinition(ImmutableDictionary<string, IServerCallHandler> callHandlers)
+ private ServerServiceDefinition(Dictionary<string, IServerCallHandler> callHandlers)
{
- this.callHandlers = callHandlers;
+ this.callHandlers = new ReadOnlyDictionary<string, IServerCallHandler>(callHandlers);
}
- internal ImmutableDictionary<string, IServerCallHandler> CallHandlers
+ internal IDictionary<string, IServerCallHandler> CallHandlers
{
get
{
@@ -115,7 +115,7 @@ namespace Grpc.Core
public ServerServiceDefinition Build()
{
- return new ServerServiceDefinition(callHandlers.ToImmutableDictionary());
+ return new ServerServiceDefinition(callHandlers);
}
}
}
diff --git a/src/csharp/Grpc.Core/packages.config b/src/csharp/Grpc.Core/packages.config
index 6cdcdf2656..9b12b9b096 100644
--- a/src/csharp/Grpc.Core/packages.config
+++ b/src/csharp/Grpc.Core/packages.config
@@ -3,5 +3,4 @@
<package id="grpc.dependencies.openssl.redist" version="1.0.2.2" targetFramework="net45" />
<package id="grpc.dependencies.zlib.redist" version="1.2.8.9" targetFramework="net45" />
<package id="Ix-Async" version="1.2.3" targetFramework="net45" />
- <package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Examples.MathServer/MathServer.cs b/src/csharp/Grpc.Examples.MathServer/MathServer.cs
index 468eefbe3e..5f7e717b0c 100644
--- a/src/csharp/Grpc.Examples.MathServer/MathServer.cs
+++ b/src/csharp/Grpc.Examples.MathServer/MathServer.cs
@@ -38,16 +38,19 @@ namespace math
{
class MainClass
{
+ const string Host = "0.0.0.0";
+ const int Port = 23456;
+
public static void Main(string[] args)
{
- string host = "0.0.0.0";
-
- Server server = new Server();
- server.AddServiceDefinition(Math.BindService(new MathServiceImpl()));
- int port = server.AddPort(host, 23456, ServerCredentials.Insecure);
+ Server server = new Server
+ {
+ Services = { Math.BindService(new MathServiceImpl()) },
+ Ports = { { Host, Port, ServerCredentials.Insecure } }
+ };
server.Start();
- Console.WriteLine("MathServer listening on port " + port);
+ Console.WriteLine("MathServer listening on port " + Port);
Console.WriteLine("Press any key to stop the server...");
Console.ReadKey();
diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
index 242d29a9a5..08aece7ef2 100644
--- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
+++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
@@ -33,6 +33,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
@@ -46,7 +47,7 @@ namespace math.Tests
/// </summary>
public class MathClientServerTest
{
- string host = "localhost";
+ const string Host = "localhost";
Server server;
Channel channel;
Math.MathClient client;
@@ -54,19 +55,14 @@ namespace math.Tests
[TestFixtureSetUp]
public void Init()
{
- server = new Server();
- server.AddServiceDefinition(Math.BindService(new MathServiceImpl()));
- int port = server.AddPort(host, Server.PickUnusedPort, ServerCredentials.Insecure);
- server.Start();
- channel = new Channel(host, port, Credentials.Insecure);
- client = Math.NewClient(channel);
-
- // TODO(jtattermusch): get rid of the custom header here once we have dedicated tests
- // for header support.
- client.HeaderInterceptor = (metadata) =>
+ server = new Server
{
- metadata.Add(new Metadata.Entry("custom-header", "abcdef"));
+ Services = { Math.BindService(new MathServiceImpl()) },
+ Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
};
+ server.Start();
+ channel = new Channel(Host, server.Ports.Single().BoundPort, Credentials.Insecure);
+ client = Math.NewClient(channel);
}
[TestFixtureTearDown]
diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs
index 67827e7b4f..4941ff35f7 100644
--- a/src/csharp/Grpc.Examples/MathGrpc.cs
+++ b/src/csharp/Grpc.Examples/MathGrpc.cs
@@ -19,24 +19,28 @@ namespace math {
static readonly Method<global::math.DivArgs, global::math.DivReply> __Method_Div = new Method<global::math.DivArgs, global::math.DivReply>(
MethodType.Unary,
+ __ServiceName,
"Div",
__Marshaller_DivArgs,
__Marshaller_DivReply);
static readonly Method<global::math.DivArgs, global::math.DivReply> __Method_DivMany = new Method<global::math.DivArgs, global::math.DivReply>(
MethodType.DuplexStreaming,
+ __ServiceName,
"DivMany",
__Marshaller_DivArgs,
__Marshaller_DivReply);
static readonly Method<global::math.FibArgs, global::math.Num> __Method_Fib = new Method<global::math.FibArgs, global::math.Num>(
MethodType.ServerStreaming,
+ __ServiceName,
"Fib",
__Marshaller_FibArgs,
__Marshaller_Num);
static readonly Method<global::math.Num, global::math.Num> __Method_Sum = new Method<global::math.Num, global::math.Num>(
MethodType.ClientStreaming,
+ __ServiceName,
"Sum",
__Marshaller_Num,
__Marshaller_Num);
@@ -45,10 +49,15 @@ namespace math {
public interface IMathClient
{
global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ global::math.DivReply Div(global::math.DivArgs request, CallOptions options);
AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, CallOptions options);
AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(CallOptions options);
AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, CallOptions options);
AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(CallOptions options);
}
// server-side interface
@@ -68,28 +77,53 @@ namespace math {
}
public global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_Div, headers, deadline);
- return Calls.BlockingUnaryCall(call, request, cancellationToken);
+ var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.BlockingUnaryCall(call, request);
+ }
+ public global::math.DivReply Div(global::math.DivArgs request, CallOptions options)
+ {
+ var call = CreateCall(__Method_Div, options);
+ return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_Div, headers, deadline);
- return Calls.AsyncUnaryCall(call, request, cancellationToken);
+ var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncUnaryCall(call, request);
+ }
+ public AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, CallOptions options)
+ {
+ var call = CreateCall(__Method_Div, options);
+ return Calls.AsyncUnaryCall(call, request);
}
public AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_DivMany, headers, deadline);
- return Calls.AsyncDuplexStreamingCall(call, cancellationToken);
+ var call = CreateCall(__Method_DivMany, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncDuplexStreamingCall(call);
+ }
+ public AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(CallOptions options)
+ {
+ var call = CreateCall(__Method_DivMany, options);
+ return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_Fib, headers, deadline);
- return Calls.AsyncServerStreamingCall(call, request, cancellationToken);
+ var call = CreateCall(__Method_Fib, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncServerStreamingCall(call, request);
+ }
+ public AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, CallOptions options)
+ {
+ var call = CreateCall(__Method_Fib, options);
+ return Calls.AsyncServerStreamingCall(call, request);
}
public AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_Sum, headers, deadline);
- return Calls.AsyncClientStreamingCall(call, cancellationToken);
+ var call = CreateCall(__Method_Sum, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncClientStreamingCall(call);
+ }
+ public AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(CallOptions options)
+ {
+ var call = CreateCall(__Method_Sum, options);
+ return Calls.AsyncClientStreamingCall(call);
}
}
diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
index 9d89698a8f..024377e216 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
+++ b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
@@ -57,11 +57,13 @@ namespace Grpc.HealthCheck.Tests
{
serviceImpl = new HealthServiceImpl();
- server = new Server();
- server.AddServiceDefinition(Grpc.Health.V1Alpha.Health.BindService(serviceImpl));
- int port = server.AddPort(Host, Server.PickUnusedPort, ServerCredentials.Insecure);
+ server = new Server
+ {
+ Services = { Grpc.Health.V1Alpha.Health.BindService(serviceImpl) },
+ Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
+ };
server.Start();
- channel = new Channel(Host, port, Credentials.Insecure);
+ channel = new Channel(Host, server.Ports.Single().BoundPort, Credentials.Insecure);
client = Grpc.Health.V1Alpha.Health.NewClient(channel);
}
diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
index 892cdb3f04..0dabc91f7c 100644
--- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
+++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
@@ -17,6 +17,7 @@ namespace Grpc.Health.V1Alpha {
static readonly Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse> __Method_Check = new Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse>(
MethodType.Unary,
+ __ServiceName,
"Check",
__Marshaller_HealthCheckRequest,
__Marshaller_HealthCheckResponse);
@@ -25,7 +26,9 @@ namespace Grpc.Health.V1Alpha {
public interface IHealthClient
{
global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options);
AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options);
}
// server-side interface
@@ -42,13 +45,23 @@ namespace Grpc.Health.V1Alpha {
}
public global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_Check, headers, deadline);
- return Calls.BlockingUnaryCall(call, request, cancellationToken);
+ var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.BlockingUnaryCall(call, request);
+ }
+ public global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options)
+ {
+ var call = CreateCall(__Method_Check, options);
+ return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_Check, headers, deadline);
- return Calls.AsyncUnaryCall(call, request, cancellationToken);
+ var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncUnaryCall(call, request);
+ }
+ public AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options)
+ {
+ var call = CreateCall(__Method_Check, options);
+ return Calls.AsyncUnaryCall(call, request);
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index abc27f811e..06a75a3351 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -87,9 +87,6 @@
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
- <Reference Include="System.Collections.Immutable">
- <HintPath>..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
- </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
index 2756ce97aa..6fa721bc1c 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
@@ -33,6 +33,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using grpc.testing;
@@ -47,7 +48,7 @@ namespace Grpc.IntegrationTesting
/// </summary>
public class InteropClientServerTest
{
- string host = "localhost";
+ const string Host = "localhost";
Server server;
Channel channel;
TestService.ITestServiceClient client;
@@ -55,16 +56,19 @@ namespace Grpc.IntegrationTesting
[TestFixtureSetUp]
public void Init()
{
- server = new Server();
- server.AddServiceDefinition(TestService.BindService(new TestServiceImpl()));
- int port = server.AddPort(host, Server.PickUnusedPort, TestCredentials.CreateTestServerCredentials());
+ server = new Server
+ {
+ Services = { TestService.BindService(new TestServiceImpl()) },
+ Ports = { { Host, ServerPort.PickUnused, TestCredentials.CreateTestServerCredentials() } }
+ };
server.Start();
var options = new List<ChannelOption>
{
new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride)
};
- channel = new Channel(host, port, TestCredentials.CreateTestClientCredentials(true), options);
+ int port = server.Ports.Single().BoundPort;
+ channel = new Channel(Host, port, TestCredentials.CreateTestClientCredentials(true), options);
client = TestService.NewClient(channel);
}
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
index bf6947e09d..504fd11857 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
@@ -88,18 +88,20 @@ namespace Grpc.IntegrationTesting
private void Run()
{
- var server = new Server();
- server.AddServiceDefinition(TestService.BindService(new TestServiceImpl()));
+ var server = new Server
+ {
+ Services = { TestService.BindService(new TestServiceImpl()) }
+ };
string host = "0.0.0.0";
int port = options.port.Value;
if (options.useTls)
{
- server.AddPort(host, port, TestCredentials.CreateTestServerCredentials());
+ server.Ports.Add(host, port, TestCredentials.CreateTestServerCredentials());
}
else
{
- server.AddPort(host, options.port.Value, ServerCredentials.Insecure);
+ server.Ports.Add(host, options.port.Value, ServerCredentials.Insecure);
}
Console.WriteLine("Running server on " + string.Format("{0}:{1}", host, port));
server.Start();
diff --git a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
index 1baf40eea2..1c398eb84e 100644
--- a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
@@ -34,6 +34,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using grpc.testing;
@@ -49,7 +50,7 @@ namespace Grpc.IntegrationTesting
/// </summary>
public class SslCredentialsTest
{
- string host = "localhost";
+ const string Host = "localhost";
Server server;
Channel channel;
TestService.ITestServiceClient client;
@@ -62,12 +63,14 @@ namespace Grpc.IntegrationTesting
File.ReadAllText(TestCredentials.ServerCertChainPath),
File.ReadAllText(TestCredentials.ServerPrivateKeyPath));
- var serverCredentials = new SslServerCredentials(new[] { keyCertPair }, rootCert);
+ var serverCredentials = new SslServerCredentials(new[] { keyCertPair }, rootCert, true);
var clientCredentials = new SslCredentials(rootCert, keyCertPair);
- server = new Server();
- server.AddServiceDefinition(TestService.BindService(new TestServiceImpl()));
- int port = server.AddPort(host, Server.PickUnusedPort, serverCredentials);
+ server = new Server
+ {
+ Services = { TestService.BindService(new TestServiceImpl()) },
+ Ports = { { Host, ServerPort.PickUnused, serverCredentials } }
+ };
server.Start();
var options = new List<ChannelOption>
@@ -75,7 +78,7 @@ namespace Grpc.IntegrationTesting
new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride)
};
- channel = new Channel(host, port, clientCredentials, options);
+ channel = new Channel(Host, server.Ports.Single().BoundPort, clientCredentials, options);
client = TestService.NewClient(channel);
}
diff --git a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
index 54d8587713..da0b7fb910 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
@@ -33,7 +33,6 @@
using System;
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
index ddcd0c2958..697acb53d8 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
@@ -22,36 +22,42 @@ namespace grpc.testing {
static readonly Method<global::grpc.testing.Empty, global::grpc.testing.Empty> __Method_EmptyCall = new Method<global::grpc.testing.Empty, global::grpc.testing.Empty>(
MethodType.Unary,
+ __ServiceName,
"EmptyCall",
__Marshaller_Empty,
__Marshaller_Empty);
static readonly Method<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleResponse> __Method_UnaryCall = new Method<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleResponse>(
MethodType.Unary,
+ __ServiceName,
"UnaryCall",
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_StreamingOutputCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>(
MethodType.ServerStreaming,
+ __ServiceName,
"StreamingOutputCall",
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
static readonly Method<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> __Method_StreamingInputCall = new Method<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse>(
MethodType.ClientStreaming,
+ __ServiceName,
"StreamingInputCall",
__Marshaller_StreamingInputCallRequest,
__Marshaller_StreamingInputCallResponse);
static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_FullDuplexCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>(
MethodType.DuplexStreaming,
+ __ServiceName,
"FullDuplexCall",
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_HalfDuplexCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>(
MethodType.DuplexStreaming,
+ __ServiceName,
"HalfDuplexCall",
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
@@ -60,13 +66,21 @@ namespace grpc.testing {
public interface ITestServiceClient
{
global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, CallOptions options);
AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, CallOptions options);
global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, CallOptions options);
AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, CallOptions options);
AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, CallOptions options);
AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options);
AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options);
AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+ AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options);
}
// server-side interface
@@ -88,43 +102,83 @@ namespace grpc.testing {
}
public global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_EmptyCall, headers, deadline);
- return Calls.BlockingUnaryCall(call, request, cancellationToken);
+ var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.BlockingUnaryCall(call, request);
+ }
+ public global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, CallOptions options)
+ {
+ var call = CreateCall(__Method_EmptyCall, options);
+ return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_EmptyCall, headers, deadline);
- return Calls.AsyncUnaryCall(call, request, cancellationToken);
+ var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncUnaryCall(call, request);
+ }
+ public AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, CallOptions options)
+ {
+ var call = CreateCall(__Method_EmptyCall, options);
+ return Calls.AsyncUnaryCall(call, request);
}
public global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_UnaryCall, headers, deadline);
- return Calls.BlockingUnaryCall(call, request, cancellationToken);
+ var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.BlockingUnaryCall(call, request);
+ }
+ public global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, CallOptions options)
+ {
+ var call = CreateCall(__Method_UnaryCall, options);
+ return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_UnaryCall, headers, deadline);
- return Calls.AsyncUnaryCall(call, request, cancellationToken);
+ var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncUnaryCall(call, request);
+ }
+ public AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, CallOptions options)
+ {
+ var call = CreateCall(__Method_UnaryCall, options);
+ return Calls.AsyncUnaryCall(call, request);
}
public AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_StreamingOutputCall, headers, deadline);
- return Calls.AsyncServerStreamingCall(call, request, cancellationToken);
+ var call = CreateCall(__Method_StreamingOutputCall, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncServerStreamingCall(call, request);
+ }
+ public AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, CallOptions options)
+ {
+ var call = CreateCall(__Method_StreamingOutputCall, options);
+ return Calls.AsyncServerStreamingCall(call, request);
}
public AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_StreamingInputCall, headers, deadline);
- return Calls.AsyncClientStreamingCall(call, cancellationToken);
+ var call = CreateCall(__Method_StreamingInputCall, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncClientStreamingCall(call);
+ }
+ public AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options)
+ {
+ var call = CreateCall(__Method_StreamingInputCall, options);
+ return Calls.AsyncClientStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_FullDuplexCall, headers, deadline);
- return Calls.AsyncDuplexStreamingCall(call, cancellationToken);
+ var call = CreateCall(__Method_FullDuplexCall, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncDuplexStreamingCall(call);
+ }
+ public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options)
+ {
+ var call = CreateCall(__Method_FullDuplexCall, options);
+ return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
- var call = CreateCall(__ServiceName, __Method_HalfDuplexCall, headers, deadline);
- return Calls.AsyncDuplexStreamingCall(call, cancellationToken);
+ var call = CreateCall(__Method_HalfDuplexCall, new CallOptions(headers, deadline, cancellationToken));
+ return Calls.AsyncDuplexStreamingCall(call);
+ }
+ public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options)
+ {
+ var call = CreateCall(__Method_HalfDuplexCall, options);
+ return Calls.AsyncDuplexStreamingCall(call);
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index 746133a7a5..7d1f84f303 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -11,5 +11,4 @@
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
<package id="NUnit" version="2.6.4" targetFramework="net45" />
- <package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
</packages> \ 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 a7be4077b8..048887bc12 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -379,7 +379,8 @@ GPR_EXPORT grpc_call *GPR_CALLTYPE
grpcsharp_channel_create_call(grpc_channel *channel, grpc_completion_queue *cq,
const char *method, const char *host,
gpr_timespec deadline) {
- return grpc_channel_create_call(channel, cq, method, host, deadline);
+ return grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+ method, host, deadline);
}
GPR_EXPORT grpc_connectivity_state GPR_CALLTYPE
@@ -792,7 +793,8 @@ grpcsharp_secure_channel_create(grpc_credentials *creds, const char *target,
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) {
+ const char **key_cert_pair_private_key_array, size_t num_key_cert_pairs,
+ int force_client_auth) {
size_t i;
grpc_server_credentials *creds;
grpc_ssl_pem_key_cert_pair *key_cert_pairs =
@@ -807,9 +809,9 @@ grpcsharp_ssl_server_credentials_create(
key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i];
}
}
- /* TODO: Add a force_client_auth parameter and pass it here. */
creds = grpc_ssl_server_credentials_create(pem_root_certs, key_cert_pairs,
- num_key_cert_pairs, 0);
+ num_key_cert_pairs,
+ force_client_auth);
gpr_free(key_cert_pairs);
return creds;
}