aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/csharp/Grpc.Core
diff options
context:
space:
mode:
Diffstat (limited to 'src/csharp/Grpc.Core')
-rw-r--r--src/csharp/Grpc.Core/.gitignore3
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.csproj22
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.nuspec8
-rw-r--r--src/csharp/Grpc.Core/Internal/CallSafeHandle.cs3
-rw-r--r--src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs10
-rw-r--r--src/csharp/Grpc.Core/Properties/AssemblyInfo.cs2
-rw-r--r--src/csharp/Grpc.Core/RpcException.cs2
-rw-r--r--src/csharp/Grpc.Core/Server.cs176
-rw-r--r--src/csharp/Grpc.Core/Status.cs5
-rw-r--r--src/csharp/Grpc.Core/packages.config4
10 files changed, 138 insertions, 97 deletions
diff --git a/src/csharp/Grpc.Core/.gitignore b/src/csharp/Grpc.Core/.gitignore
index 8d4a6c08a8..c2dd664167 100644
--- a/src/csharp/Grpc.Core/.gitignore
+++ b/src/csharp/Grpc.Core/.gitignore
@@ -1,2 +1,3 @@
bin
-obj \ No newline at end of file
+obj
+*.nupkg
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 78ba32b277..0b85392e15 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props')" />
+ <Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -10,6 +12,7 @@
<RootNamespace>Grpc.Core</RootNamespace>
<AssemblyName>Grpc.Core</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <NuGetPackageImportStamp>8bb563fb</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -32,7 +35,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable">
- <HintPath>..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
+ <HintPath>..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -92,7 +95,7 @@
ignored, which gives us the desired effect. -->
<When Condition=" '$(OS)' != 'Unix' ">
<ItemGroup>
- <Content Include="..\..\..\vsprojects\vs2013\Debug\grpc_csharp_ext.dll">
+ <Content Include="..\..\..\vsprojects\Debug\grpc_csharp_ext.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
@@ -100,7 +103,16 @@
<Otherwise />
</Choose>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
- <ItemGroup>
- <Folder Include="Stub\" />
- </ItemGroup>
+ <ItemGroup />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.props'))" />
+ <Error Condition="!Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets'))" />
+ <Error Condition="!Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.props'))" />
+ <Error Condition="!Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets'))" />
+ </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')" />
</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 af8a8869ca..4865ead555 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.nuspec
+++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<package >
+<package>
<metadata>
<id>Grpc.Core</id>
<title>gRPC Core</title>
@@ -7,7 +7,7 @@
<description>Core C# implementation of gRPC - an RPC library and framework. See project site for more info.
This is an experimental release, not ready to use.
</description>
- <version>0.1.0</version>
+ <version>0.2.1</version>
<authors>Google Inc.</authors>
<owners>jtattermusch</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
@@ -16,6 +16,10 @@
<releaseNotes>The first experimental release. Not ready to use.</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
+ <dependencies>
+ <dependency id="Microsoft.Bcl.Immutable" version="1.0.34" />
+ <dependency id="grpc.native.csharp_ext" version="0.6.0.0" />
+ </dependencies>
</metadata>
<files>
<file src="bin/Release/Grpc.Core.dll" target="lib/net45" />
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index 14add60c72..c97a3bc2b1 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -33,6 +33,7 @@ using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Grpc.Core;
+using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
@@ -180,7 +181,7 @@ namespace Grpc.Core.Internal
private static void AssertCallOk(GRPCCallError callError)
{
- Trace.Assert(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK");
+ Preconditions.CheckState(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK");
}
private static uint GetFlags(bool buffered)
diff --git a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
index a59da09822..8080643d8c 100644
--- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
@@ -35,6 +35,7 @@ using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Runtime.InteropServices;
+using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
@@ -105,9 +106,9 @@ namespace Grpc.Core.Internal
grpcsharp_server_shutdown_and_notify_CALLBACK(this, callback);
}
- public GRPCCallError RequestCall(CompletionQueueSafeHandle cq, CompletionCallbackDelegate callback)
+ public void RequestCall(CompletionQueueSafeHandle cq, CompletionCallbackDelegate callback)
{
- return grpcsharp_server_request_call(this, cq, callback);
+ AssertCallOk(grpcsharp_server_request_call(this, cq, callback));
}
protected override bool ReleaseHandle()
@@ -115,5 +116,10 @@ namespace Grpc.Core.Internal
grpcsharp_server_destroy(handle);
return true;
}
+
+ private static void AssertCallOk(GRPCCallError callError)
+ {
+ Preconditions.CheckState(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK");
+ }
}
}
diff --git a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
index 168939cf8c..81218cb67e 100644
--- a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
@@ -9,6 +9,6 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.1.*")]
+[assembly: AssemblyVersion("0.2.*")]
[assembly: InternalsVisibleTo("Grpc.Core.Tests")]
diff --git a/src/csharp/Grpc.Core/RpcException.cs b/src/csharp/Grpc.Core/RpcException.cs
index 433d87215e..c58578286b 100644
--- a/src/csharp/Grpc.Core/RpcException.cs
+++ b/src/csharp/Grpc.Core/RpcException.cs
@@ -42,7 +42,7 @@ namespace Grpc.Core
{
private readonly Status status;
- public RpcException(Status status)
+ public RpcException(Status status) : base(status.ToString())
{
this.status = status;
}
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index f086fa8beb..e686cdddef 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -38,27 +38,29 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Grpc.Core.Internal;
+using Grpc.Core.Utils;
namespace Grpc.Core
{
/// <summary>
- /// Server is implemented only to be able to do
- /// in-process testing.
+ /// A gRPC server.
/// </summary>
public class Server
{
- // TODO: make sure the delegate doesn't get garbage collected while
+ // TODO(jtattermusch) : make sure the delegate doesn't get garbage collected while
// native callbacks are in the completion queue.
readonly ServerShutdownCallbackDelegate serverShutdownHandler;
readonly CompletionCallbackDelegate newServerRpcHandler;
- readonly BlockingCollection<NewRpcInfo> newRpcQueue = new BlockingCollection<NewRpcInfo>();
readonly ServerSafeHandle handle;
+ readonly object myLock = new object();
readonly Dictionary<string, IServerCallHandler> callHandlers = new Dictionary<string, IServerCallHandler>();
-
readonly TaskCompletionSource<object> shutdownTcs = new TaskCompletionSource<object>();
+ bool startRequested;
+ bool shutdownRequested;
+
public Server()
{
this.handle = ServerSafeHandle.NewServer(GetCompletionQueue(), IntPtr.Zero);
@@ -66,71 +68,81 @@ namespace Grpc.Core
this.serverShutdownHandler = HandleServerShutdown;
}
- // only call this before Start()
+ /// <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 AddServiceDefinition(ServerServiceDefinition serviceDefinition)
{
- foreach (var entry in serviceDefinition.CallHandlers)
+ lock (myLock)
{
- callHandlers.Add(entry.Key, entry.Value);
+ Preconditions.CheckState(!startRequested);
+ foreach (var entry in serviceDefinition.CallHandlers)
+ {
+ callHandlers.Add(entry.Key, entry.Value);
+ }
}
}
- // only call before Start()
+ /// <summary>
+ /// Add a non-secure port on which server should listen.
+ /// Only call this before Start().
+ /// </summary>
public int AddListeningPort(string addr)
{
- return handle.AddListeningPort(addr);
- }
-
- // only call before Start()
- public int AddListeningPort(string addr, ServerCredentials credentials)
- {
- using (var nativeCredentials = credentials.ToNativeCredentials())
+ lock (myLock)
{
- return handle.AddListeningPort(addr, nativeCredentials);
+ Preconditions.CheckState(!startRequested);
+ return handle.AddListeningPort(addr);
}
}
- public void Start()
- {
- handle.Start();
-
- // TODO: this basically means the server is single threaded....
- StartHandlingRpcs();
- }
-
/// <summary>
- /// Requests and handles single RPC call.
+ /// Add a secure port on which server should listen.
+ /// Only call this before Start().
/// </summary>
- internal void RunRpc()
+ public int AddListeningPort(string addr, ServerCredentials credentials)
{
- AllowOneRpc();
-
- try
+ lock (myLock)
{
- var rpcInfo = newRpcQueue.Take();
-
- // Console.WriteLine("Server received RPC " + rpcInfo.Method);
-
- IServerCallHandler callHandler;
- if (!callHandlers.TryGetValue(rpcInfo.Method, out callHandler))
+ Preconditions.CheckState(!startRequested);
+ using (var nativeCredentials = credentials.ToNativeCredentials())
{
- callHandler = new NoSuchMethodCallHandler();
+ return handle.AddListeningPort(addr, nativeCredentials);
}
- callHandler.StartCall(rpcInfo.Method, rpcInfo.Call, GetCompletionQueue());
}
- catch (Exception e)
+ }
+
+ /// <summary>
+ /// Starts the server.
+ /// </summary>
+ public void Start()
+ {
+ lock (myLock)
{
- Console.WriteLine("Exception while handling RPC: " + e);
+ Preconditions.CheckState(!startRequested);
+ startRequested = true;
+
+ handle.Start();
+ AllowOneRpc();
}
}
/// <summary>
/// Requests server shutdown and when there are no more calls being serviced,
- /// cleans up used resources.
+ /// cleans up used resources. The returned task finishes when shutdown procedure
+ /// is complete.
/// </summary>
- /// <returns>The async.</returns>
public async Task ShutdownAsync()
{
+ lock (myLock)
+ {
+ Preconditions.CheckState(startRequested);
+ Preconditions.CheckState(!shutdownRequested);
+ shutdownRequested = true;
+ }
+
handle.ShutdownAndNotify(serverShutdownHandler);
await shutdownTcs.Task;
handle.Dispose();
@@ -152,19 +164,43 @@ namespace Grpc.Core
handle.Dispose();
}
- private async Task StartHandlingRpcs()
+ /// <summary>
+ /// Allows one new RPC call to be received by server.
+ /// </summary>
+ private void AllowOneRpc()
{
- while (true)
+ lock (myLock)
{
- await Task.Factory.StartNew(RunRpc);
+ if (!shutdownRequested)
+ {
+ handle.RequestCall(GetCompletionQueue(), newServerRpcHandler);
+ }
}
}
- private void AllowOneRpc()
+ /// <summary>
+ /// Selects corresponding handler for given call and handles the call.
+ /// </summary>
+ private void InvokeCallHandler(CallSafeHandle call, string method)
{
- AssertCallOk(handle.RequestCall(GetCompletionQueue(), newServerRpcHandler));
+ try
+ {
+ IServerCallHandler callHandler;
+ if (!callHandlers.TryGetValue(method, out callHandler))
+ {
+ callHandler = new NoSuchMethodCallHandler();
+ }
+ callHandler.StartCall(method, call, GetCompletionQueue());
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Exception while handling RPC: " + e);
+ }
}
+ /// <summary>
+ /// Handles the native callback.
+ /// </summary>
private void HandleNewServerRpc(GRPCOpError error, IntPtr batchContextPtr)
{
try
@@ -176,13 +212,16 @@ namespace Grpc.Core
// TODO: handle error
}
- var rpcInfo = new NewRpcInfo(ctx.GetServerRpcNewCall(), ctx.GetServerRpcNewMethod());
+ CallSafeHandle call = ctx.GetServerRpcNewCall();
+ string method = ctx.GetServerRpcNewMethod();
// after server shutdown, the callback returns with null call
- if (!rpcInfo.Call.IsInvalid)
+ if (!call.IsInvalid)
{
- newRpcQueue.Add(rpcInfo);
+ Task.Run(() => InvokeCallHandler(call, method));
}
+
+ AllowOneRpc();
}
catch (Exception e)
{
@@ -190,6 +229,10 @@ namespace Grpc.Core
}
}
+ /// <summary>
+ /// Handles native callback.
+ /// </summary>
+ /// <param name="eventPtr"></param>
private void HandleServerShutdown(IntPtr eventPtr)
{
try
@@ -202,42 +245,9 @@ namespace Grpc.Core
}
}
- private static void AssertCallOk(GRPCCallError callError)
- {
- Trace.Assert(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK");
- }
-
private static CompletionQueueSafeHandle GetCompletionQueue()
{
return GrpcEnvironment.ThreadPool.CompletionQueue;
}
-
- private struct NewRpcInfo
- {
- private CallSafeHandle call;
- private string method;
-
- public NewRpcInfo(CallSafeHandle call, string method)
- {
- this.call = call;
- this.method = method;
- }
-
- public CallSafeHandle Call
- {
- get
- {
- return this.call;
- }
- }
-
- public string Method
- {
- get
- {
- return this.method;
- }
- }
- }
}
}
diff --git a/src/csharp/Grpc.Core/Status.cs b/src/csharp/Grpc.Core/Status.cs
index 080bbdc2f5..7d76aec4d1 100644
--- a/src/csharp/Grpc.Core/Status.cs
+++ b/src/csharp/Grpc.Core/Status.cs
@@ -69,5 +69,10 @@ namespace Grpc.Core
return detail;
}
}
+
+ public override string ToString()
+ {
+ return string.Format("Status(StatusCode={0}, Detail=\"{1}\")", statusCode, detail);
+ }
}
}
diff --git a/src/csharp/Grpc.Core/packages.config b/src/csharp/Grpc.Core/packages.config
index cf711ac362..71967de56e 100644
--- a/src/csharp/Grpc.Core/packages.config
+++ b/src/csharp/Grpc.Core/packages.config
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="System.Collections.Immutable" version="1.1.34-rc" targetFramework="net45" />
+ <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="Microsoft.Bcl.Immutable" version="1.0.34" targetFramework="net45" />
</packages> \ No newline at end of file