diff options
author | 2015-09-08 10:55:20 -0700 | |
---|---|---|
committer | 2015-10-06 14:07:37 -0700 | |
commit | 5bd75d789c77891b6dfee3dd619a67ec5be444d3 (patch) | |
tree | 42d2013e32473f669128cef179db9fa44a5f6849 /src/csharp/Grpc.Core | |
parent | 4d1fc5526160470b7d50a78062b80c0f5f4229e4 (diff) |
implement C# wrapping for plugin API
Diffstat (limited to 'src/csharp/Grpc.Core')
-rw-r--r-- | src/csharp/Grpc.Core/Credentials.cs | 52 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Grpc.Core.csproj | 1 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs | 8 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs | 112 |
4 files changed, 173 insertions, 0 deletions
diff --git a/src/csharp/Grpc.Core/Credentials.cs b/src/csharp/Grpc.Core/Credentials.cs index 4fcac0c4c0..e653d3688c 100644 --- a/src/csharp/Grpc.Core/Credentials.cs +++ b/src/csharp/Grpc.Core/Credentials.cs @@ -32,10 +32,17 @@ #endregion using System; +using System.Collections.Generic; +using System.Threading.Tasks; + using Grpc.Core.Internal; +using Grpc.Core.Utils; namespace Grpc.Core { + // TODO: rename + public delegate Task AsyncAuthInterceptor(string authUri, Metadata metadata); + /// <summary> /// Client-side credentials. Used for creation of a secure channel. /// </summary> @@ -135,4 +142,49 @@ namespace Grpc.Core return CredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair); } } + + /// <summary> + /// Client-side credentials that delegate metadata based auth to an interceptor. + /// </summary> + public partial class MetadataCredentials : Credentials + { + readonly AsyncAuthInterceptor interceptor; + + public MetadataCredentials(AsyncAuthInterceptor interceptor) + { + this.interceptor = interceptor; + } + + internal override CredentialsSafeHandle ToNativeCredentials() + { + NativeMetadataCredentialsPlugin plugin = new NativeMetadataCredentialsPlugin(interceptor); + return plugin.Credentials; + } + } + + public sealed class CompositeCredentials : Credentials + { + readonly List<Credentials> credentials; + + public CompositeCredentials(params Credentials[] credentials) + { + Preconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials."); + this.credentials = new List<Credentials>(credentials); + } + + public static CompositeCredentials Create(params Credentials[] credentials) + { + return new CompositeCredentials(credentials); + } + + internal override CredentialsSafeHandle ToNativeCredentials() + { + var nativeComposite = credentials[0].ToNativeCredentials(); + for (int i = 1; i < credentials.Count; i++) + { + nativeComposite = CredentialsSafeHandle.CreateComposite(nativeComposite, credentials[i].ToNativeCredentials()); + } + return nativeComposite; + } + } } diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index ad2af17bc7..04c3eda113 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -49,6 +49,7 @@ <Compile Include="AsyncDuplexStreamingCall.cs" /> <Compile Include="AsyncServerStreamingCall.cs" /> <Compile Include="IClientStreamWriter.cs" /> + <Compile Include="Internal\NativeMetadataCredentialsPlugin.cs" /> <Compile Include="Internal\INativeCall.cs" /> <Compile Include="IServerStreamWriter.cs" /> <Compile Include="IAsyncStreamWriter.cs" /> diff --git a/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs index feed335362..bab45108e0 100644 --- a/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs @@ -44,6 +44,9 @@ namespace Grpc.Core.Internal static extern CredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); [DllImport("grpc_csharp_ext.dll")] + static extern CredentialsSafeHandle grpcsharp_composite_credentials_create(CredentialsSafeHandle creds1, CredentialsSafeHandle creds2); + + [DllImport("grpc_csharp_ext.dll")] static extern void grpcsharp_credentials_release(IntPtr credentials); private CredentialsSafeHandle() @@ -69,6 +72,11 @@ namespace Grpc.Core.Internal } } + public static CredentialsSafeHandle CreateComposite(CredentialsSafeHandle creds1, CredentialsSafeHandle creds2) + { + return grpcsharp_composite_credentials_create(creds1, creds2); + } + protected override bool ReleaseHandle() { grpcsharp_credentials_release(handle); diff --git a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs new file mode 100644 index 0000000000..6662a73b17 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs @@ -0,0 +1,112 @@ +#region Copyright notice and license +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal delegate void NativeMetadataInterceptor(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy); + + internal class NativeMetadataCredentialsPlugin + { + const string GetMetadataExceptionMsg = "Exception occured in metadata credentials plugin."; + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeMetadataCredentialsPlugin>(); + + [DllImport("grpc_csharp_ext.dll")] + static extern CredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor); + + [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] + static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + + AsyncAuthInterceptor interceptor; + GCHandle gcHandle; + NativeMetadataInterceptor nativeInterceptor; + CredentialsSafeHandle credentials; + + public NativeMetadataCredentialsPlugin(AsyncAuthInterceptor interceptor) + { + this.interceptor = Preconditions.CheckNotNull(interceptor, "interceptor"); + this.nativeInterceptor = NativeMetadataInterceptorHandler; + + // Make sure the callback doesn't get garbage collected until it is destroyed. + this.gcHandle = GCHandle.Alloc(this.nativeInterceptor, GCHandleType.Normal); + this.credentials = grpcsharp_metadata_credentials_create_from_plugin(nativeInterceptor); + } + + public CredentialsSafeHandle Credentials + { + get { return credentials; } + } + + private void NativeMetadataInterceptorHandler(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy) + { + if (isDestroy) + { + gcHandle.Free(); + return; + } + + try + { + string serviceUrl = Marshal.PtrToStringAnsi(serviceUrlPtr); + StartGetMetadata(serviceUrl, callbackPtr, userDataPtr); + } + catch (Exception e) + { + grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, null, StatusCode.Unknown, GetMetadataExceptionMsg); + Logger.Error(e, GetMetadataExceptionMsg); + } + } + + private async void StartGetMetadata(string serviceUrl, IntPtr callbackPtr, IntPtr userDataPtr) + { + try + { + var metadata = new Metadata(); + await interceptor(serviceUrl, metadata); + using (var metadataArray = MetadataArraySafeHandle.Create(metadata)) + { + grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, metadataArray, StatusCode.OK, null); + } + } + catch (Exception e) + { + grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, null, StatusCode.Unknown, GetMetadataExceptionMsg); + Logger.Error(e, GetMetadataExceptionMsg); + } + } + } +} |