From 08dea32d24d68a0fc656169e2cc1b39f4cb18678 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch <jtattermusch@google.com> Date: Mon, 26 Oct 2015 17:34:10 -0700 Subject: [PATCH] update C# to the new C core auth API --- src/csharp/Grpc.Core.Tests/FakeCredentials.cs | 4 +- src/csharp/Grpc.Core/CallCredentials.cs | 10 +-- src/csharp/Grpc.Core/Channel.cs | 4 +- src/csharp/Grpc.Core/ChannelCredentials.cs | 16 ++--- src/csharp/Grpc.Core/Grpc.Core.csproj | 3 +- .../Internal/CallCredentialsSafeHandle.cs | 64 +++++++++++++++++++ .../Grpc.Core/Internal/CallSafeHandle.cs | 4 +- ...dle.cs => ChannelCredentialsSafeHandle.cs} | 24 +++---- .../Grpc.Core/Internal/ChannelSafeHandle.cs | 6 +- .../NativeMetadataCredentialsPlugin.cs | 6 +- src/csharp/ext/grpc_csharp_ext.c | 38 +++++++---- 11 files changed, 129 insertions(+), 50 deletions(-) create mode 100644 src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs rename src/csharp/Grpc.Core/Internal/{CredentialsSafeHandle.cs => ChannelCredentialsSafeHandle.cs} (68%) diff --git a/src/csharp/Grpc.Core.Tests/FakeCredentials.cs b/src/csharp/Grpc.Core.Tests/FakeCredentials.cs index 87d55cd276..144b8320b9 100644 --- a/src/csharp/Grpc.Core.Tests/FakeCredentials.cs +++ b/src/csharp/Grpc.Core.Tests/FakeCredentials.cs @@ -57,7 +57,7 @@ namespace Grpc.Core.Tests get { return composable; } } - internal override CredentialsSafeHandle ToNativeCredentials() + internal override ChannelCredentialsSafeHandle ToNativeCredentials() { return null; } @@ -65,7 +65,7 @@ namespace Grpc.Core.Tests internal class FakeCallCredentials : CallCredentials { - internal override CredentialsSafeHandle ToNativeCredentials() + internal override CallCredentialsSafeHandle ToNativeCredentials() { return null; } diff --git a/src/csharp/Grpc.Core/CallCredentials.cs b/src/csharp/Grpc.Core/CallCredentials.cs index 400a9825de..5ea179dfea 100644 --- a/src/csharp/Grpc.Core/CallCredentials.cs +++ b/src/csharp/Grpc.Core/CallCredentials.cs @@ -78,7 +78,7 @@ namespace Grpc.Core /// Creates native object for the credentials. /// </summary> /// <returns>The native credentials.</returns> - internal abstract CredentialsSafeHandle ToNativeCredentials(); + internal abstract CallCredentialsSafeHandle ToNativeCredentials(); } /// <summary> @@ -98,7 +98,7 @@ namespace Grpc.Core this.interceptor = Preconditions.CheckNotNull(interceptor); } - internal override CredentialsSafeHandle ToNativeCredentials() + internal override CallCredentialsSafeHandle ToNativeCredentials() { NativeMetadataCredentialsPlugin plugin = new NativeMetadataCredentialsPlugin(interceptor); return plugin.Credentials; @@ -123,14 +123,14 @@ namespace Grpc.Core this.credentials = new List<CallCredentials>(credentials); } - internal override CredentialsSafeHandle ToNativeCredentials() + internal override CallCredentialsSafeHandle ToNativeCredentials() { return ToNativeRecursive(0); } // Recursive descent makes managing lifetime of intermediate CredentialSafeHandle instances easier. // In practice, we won't usually see composites from more than two credentials anyway. - private CredentialsSafeHandle ToNativeRecursive(int startIndex) + private CallCredentialsSafeHandle ToNativeRecursive(int startIndex) { if (startIndex == credentials.Count - 1) { @@ -140,7 +140,7 @@ namespace Grpc.Core using (var cred1 = credentials[startIndex].ToNativeCredentials()) using (var cred2 = ToNativeRecursive(startIndex + 1)) { - var nativeComposite = CredentialsSafeHandle.CreateComposite(cred1, cred2); + var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2); if (nativeComposite.IsInvalid) { throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials."); diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs index 6b99055d4c..f5eec969f5 100644 --- a/src/csharp/Grpc.Core/Channel.cs +++ b/src/csharp/Grpc.Core/Channel.cs @@ -75,8 +75,8 @@ namespace Grpc.Core this.options = options != null ? new List<ChannelOption>(options) : new List<ChannelOption>(); EnsureUserAgentChannelOption(this.options); - using (CredentialsSafeHandle nativeCredentials = credentials.ToNativeCredentials()) - using (ChannelArgsSafeHandle nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options)) + using (var nativeCredentials = credentials.ToNativeCredentials()) + using (var nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options)) { if (nativeCredentials != null) { diff --git a/src/csharp/Grpc.Core/ChannelCredentials.cs b/src/csharp/Grpc.Core/ChannelCredentials.cs index 9d2bcdabe8..5d96958e7c 100644 --- a/src/csharp/Grpc.Core/ChannelCredentials.cs +++ b/src/csharp/Grpc.Core/ChannelCredentials.cs @@ -76,7 +76,7 @@ namespace Grpc.Core /// should be created. /// </summary> /// <returns>The native credentials.</returns> - internal abstract CredentialsSafeHandle ToNativeCredentials(); + internal abstract ChannelCredentialsSafeHandle ToNativeCredentials(); /// <summary> /// Returns <c>true</c> if this credential type allows being composed by <c>CompositeCredentials</c>. @@ -88,7 +88,7 @@ namespace Grpc.Core private sealed class InsecureCredentialsImpl : ChannelCredentials { - internal override CredentialsSafeHandle ToNativeCredentials() + internal override ChannelCredentialsSafeHandle ToNativeCredentials() { return null; } @@ -160,9 +160,9 @@ namespace Grpc.Core get { return true; } } - internal override CredentialsSafeHandle ToNativeCredentials() + internal override ChannelCredentialsSafeHandle ToNativeCredentials() { - return CredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair); + return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair); } } @@ -188,12 +188,12 @@ namespace Grpc.Core Preconditions.CheckArgument(channelCredentials.IsComposable, "Supplied channel credentials do not allow composition."); } - internal override CredentialsSafeHandle ToNativeCredentials() + internal override ChannelCredentialsSafeHandle ToNativeCredentials() { - using (var cred1 = channelCredentials.ToNativeCredentials()) - using (var cred2 = callCredentials.ToNativeCredentials()) + using (var channelCreds = channelCredentials.ToNativeCredentials()) + using (var callCreds = callCredentials.ToNativeCredentials()) { - var nativeComposite = CredentialsSafeHandle.CreateComposite(cred1, cred2); + var nativeComposite = ChannelCredentialsSafeHandle.CreateComposite(channelCreds, callCreds); if (nativeComposite.IsInvalid) { throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials."); diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 92d4e19eac..1e98ab7747 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -80,7 +80,6 @@ <Compile Include="ServerServiceDefinition.cs" /> <Compile Include="Utils\AsyncStreamExtensions.cs" /> <Compile Include="Utils\BenchmarkUtil.cs" /> - <Compile Include="Internal\CredentialsSafeHandle.cs" /> <Compile Include="ChannelCredentials.cs" /> <Compile Include="Internal\ChannelArgsSafeHandle.cs" /> <Compile Include="Internal\AsyncCompletion.cs" /> @@ -119,6 +118,8 @@ <Compile Include="CompressionLevel.cs" /> <Compile Include="WriteOptions.cs" /> <Compile Include="ContextPropagationToken.cs" /> + <Compile Include="Internal\CallCredentialsSafeHandle.cs" /> + <Compile Include="Internal\ChannelCredentialsSafeHandle.cs" /> </ItemGroup> <ItemGroup> <None Include="Grpc.Core.nuspec" /> diff --git a/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs new file mode 100644 index 0000000000..3678c7dd86 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs @@ -0,0 +1,64 @@ +#region Copyright notice and license +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// grpc_call_credentials from <c>grpc/grpc_security.h</c> + /// </summary> + internal class CallCredentialsSafeHandle : SafeHandleZeroIsInvalid + { + [DllImport("grpc_csharp_ext.dll")] + static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + + [DllImport("grpc_csharp_ext.dll")] + static extern void grpcsharp_call_credentials_release(IntPtr credentials); + + private CallCredentialsSafeHandle() + { + } + + public static CallCredentialsSafeHandle CreateComposite(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2) + { + return grpcsharp_composite_call_credentials_create(creds1, creds2); + } + + protected override bool ReleaseHandle() + { + grpcsharp_call_credentials_release(handle); + return true; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs index 0be7a4dd3a..4c7c614613 100644 --- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs @@ -99,7 +99,7 @@ namespace Grpc.Core.Internal BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_set_credentials(CallSafeHandle call, CredentialsSafeHandle credentials); + static extern GRPCCallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); [DllImport("grpc_csharp_ext.dll")] static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); @@ -116,7 +116,7 @@ namespace Grpc.Core.Internal this.completionRegistry = completionRegistry; } - public void SetCredentials(CredentialsSafeHandle credentials) + public void SetCredentials(CallCredentialsSafeHandle credentials) { grpcsharp_call_set_credentials(this, credentials).CheckOk(); } diff --git a/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs similarity index 68% rename from src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs rename to src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs index bab45108e0..8a58c64478 100644 --- a/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs @@ -36,31 +36,31 @@ using System.Threading.Tasks; namespace Grpc.Core.Internal { /// <summary> - /// grpc_credentials from <c>grpc/grpc_security.h</c> + /// grpc_channel_credentials from <c>grpc/grpc_security.h</c> /// </summary> - internal class CredentialsSafeHandle : SafeHandleZeroIsInvalid + internal class ChannelCredentialsSafeHandle : SafeHandleZeroIsInvalid { [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - static extern CredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); + static extern ChannelCredentialsSafeHandle 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); + static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_credentials_release(IntPtr credentials); + static extern void grpcsharp_channel_credentials_release(IntPtr credentials); - private CredentialsSafeHandle() + private ChannelCredentialsSafeHandle() { } - public static CredentialsSafeHandle CreateNullCredentials() + public static ChannelCredentialsSafeHandle CreateNullCredentials() { - var creds = new CredentialsSafeHandle(); + var creds = new ChannelCredentialsSafeHandle(); creds.SetHandle(IntPtr.Zero); return creds; } - public static CredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair) + public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair) { if (keyCertPair != null) { @@ -72,14 +72,14 @@ namespace Grpc.Core.Internal } } - public static CredentialsSafeHandle CreateComposite(CredentialsSafeHandle creds1, CredentialsSafeHandle creds2) + public static ChannelCredentialsSafeHandle CreateComposite(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds) { - return grpcsharp_composite_credentials_create(creds1, creds2); + return grpcsharp_composite_channel_credentials_create(channelCreds, callCreds); } protected override bool ReleaseHandle() { - grpcsharp_credentials_release(handle); + grpcsharp_channel_credentials_release(handle); return true; } } diff --git a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs index d270d77526..4c14110679 100644 --- a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs @@ -44,7 +44,7 @@ namespace Grpc.Core.Internal static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); [DllImport("grpc_csharp_ext.dll")] - static extern ChannelSafeHandle grpcsharp_secure_channel_create(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); [DllImport("grpc_csharp_ext.dll")] static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); @@ -74,7 +74,7 @@ namespace Grpc.Core.Internal return grpcsharp_insecure_channel_create(target, channelArgs); } - public static ChannelSafeHandle CreateSecure(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs) + public static ChannelSafeHandle CreateSecure(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs) { // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle. // Doing so would make object finalizer crash if we end up abandoning the handle. @@ -82,7 +82,7 @@ namespace Grpc.Core.Internal return grpcsharp_secure_channel_create(credentials, target, channelArgs); } - public CallSafeHandle CreateCall(CompletionRegistry registry, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CredentialsSafeHandle credentials) + public CallSafeHandle CreateCall(CompletionRegistry registry, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CallCredentialsSafeHandle credentials) { var result = grpcsharp_channel_create_call(this, parentCall, propagationMask, cq, method, host, deadline); if (credentials != null) diff --git a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs index f76492cba4..2a571cd6c9 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs @@ -46,7 +46,7 @@ namespace Grpc.Core.Internal static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeMetadataCredentialsPlugin>(); [DllImport("grpc_csharp_ext.dll")] - static extern CredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor); + static extern CallCredentialsSafeHandle 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); @@ -54,7 +54,7 @@ namespace Grpc.Core.Internal AsyncAuthInterceptor interceptor; GCHandle gcHandle; NativeMetadataInterceptor nativeInterceptor; - CredentialsSafeHandle credentials; + CallCredentialsSafeHandle credentials; public NativeMetadataCredentialsPlugin(AsyncAuthInterceptor interceptor) { @@ -66,7 +66,7 @@ namespace Grpc.Core.Internal this.credentials = grpcsharp_metadata_credentials_create_from_plugin(nativeInterceptor); } - public CredentialsSafeHandle Credentials + public CallCredentialsSafeHandle Credentials { get { return credentials; } } diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 679ca43d74..183931936e 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -785,9 +785,10 @@ grpcsharp_call_send_initial_metadata(grpc_call *call, NULL); } -GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_set_credentials(grpc_call *call, - grpc_credentials *creds) { - return grpc_call_set_credentials(call, creds); +GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_set_credentials( + grpc_call *call, + grpc_call_credentials *creds) { + return grpc_call_set_credentials(call, creds); } /* Server */ @@ -834,7 +835,7 @@ grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq, /* Security */ -GPR_EXPORT grpc_credentials *GPR_CALLTYPE +GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE grpcsharp_ssl_credentials_create(const char *pem_root_certs, const char *key_cert_pair_cert_chain, const char *key_cert_pair_private_key) { @@ -850,12 +851,19 @@ grpcsharp_ssl_credentials_create(const char *pem_root_certs, } } -GPR_EXPORT void GPR_CALLTYPE grpcsharp_credentials_release(grpc_credentials *creds) { - grpc_credentials_release(creds); +GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_credentials_release( + grpc_channel_credentials *creds) { + grpc_channel_credentials_release(creds); +} + +GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_credentials_release( + grpc_call_credentials *creds) { + grpc_call_credentials_release(creds); } GPR_EXPORT grpc_channel *GPR_CALLTYPE -grpcsharp_secure_channel_create(grpc_credentials *creds, const char *target, +grpcsharp_secure_channel_create(grpc_channel_credentials *creds, + const char *target, const grpc_channel_args *args) { return grpc_secure_channel_create(creds, target, args, NULL); } @@ -897,10 +905,16 @@ grpcsharp_server_add_secure_http2_port(grpc_server *server, const char *addr, return grpc_server_add_secure_http2_port(server, addr, creds); } -GPR_EXPORT grpc_credentials *GPR_CALLTYPE grpcsharp_composite_credentials_create( - grpc_credentials *creds1, - grpc_credentials *creds2) { - return grpc_composite_credentials_create(creds1, creds2, NULL); +GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE grpcsharp_composite_channel_credentials_create( + grpc_channel_credentials *channel_creds, + grpc_call_credentials *call_creds) { + return grpc_composite_channel_credentials_create(channel_creds, call_creds, NULL); +} + +GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_composite_call_credentials_create( + grpc_call_credentials *creds1, + grpc_call_credentials *creds2) { + return grpc_composite_call_credentials_create(creds1, creds2, NULL); } /* Metadata credentials plugin */ @@ -929,7 +943,7 @@ static void grpcsharp_metadata_credentials_destroy_handler(void *state) { interceptor(state, NULL, NULL, NULL, 1); } -GPR_EXPORT grpc_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_create_from_plugin( +GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_create_from_plugin( grpcsharp_metadata_interceptor_func metadata_interceptor) { grpc_metadata_credentials_plugin plugin; plugin.get_metadata = grpcsharp_get_metadata_handler; -- GitLab