1 #region Copyright notice and license
2 
3 // Copyright 2017 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #endregion
18 
19 using System;
20 using System.Collections.Generic;
21 using System.Runtime.InteropServices;
22 using System.Text;
23 using Grpc.Core;
24 using Grpc.Core.Utils;
25 
26 namespace Grpc.Core.Internal
27 {
28     /// <summary>
29     /// grpc_auth_context
30     /// </summary>
31     internal class AuthContextSafeHandle : SafeHandleZeroIsInvalid
32     {
33         static readonly NativeMethods Native = NativeMethods.Get();
34 
AuthContextSafeHandle()35         private AuthContextSafeHandle()
36         {
37         }
38 
39         /// <summary>
40         /// Copies contents of the native auth context into a new <c>AuthContext</c> instance.
41         /// </summary>
ToAuthContext()42         public AuthContext ToAuthContext()
43         {
44             if (IsInvalid)
45             {
46                 return new AuthContext(null, new Dictionary<string, List<AuthProperty>>());
47             }
48 
49             var peerIdentityPropertyName = Marshal.PtrToStringAnsi(Native.grpcsharp_auth_context_peer_identity_property_name(this));
50 
51             var propertiesDict = new Dictionary<string, List<AuthProperty>>();
52 
53             var it = Native.grpcsharp_auth_context_property_iterator(this);
54             IntPtr authPropertyPtr = IntPtr.Zero;
55             while ((authPropertyPtr = Native.grpcsharp_auth_property_iterator_next(ref it)) != IntPtr.Zero)
56             {
57                 var authProperty = PtrToAuthProperty(authPropertyPtr);
58 
59                 if (!propertiesDict.ContainsKey(authProperty.Name))
60                 {
61                     propertiesDict[authProperty.Name] = new List<AuthProperty>();
62                 }
63                 propertiesDict[authProperty.Name].Add(authProperty);
64             }
65 
66             return new AuthContext(peerIdentityPropertyName, propertiesDict);
67         }
68 
ReleaseHandle()69         protected override bool ReleaseHandle()
70         {
71             Native.grpcsharp_auth_context_release(handle);
72             return true;
73         }
74 
PtrToAuthProperty(IntPtr authPropertyPtr)75         private AuthProperty PtrToAuthProperty(IntPtr authPropertyPtr)
76         {
77             #pragma warning disable 0618
78             // We need to use the obsolete non-generic version of Marshal.PtrToStructure, because the generic version is not available in net45
79             var nativeAuthProperty = (NativeAuthProperty) Marshal.PtrToStructure(authPropertyPtr, typeof(NativeAuthProperty));
80             #pragma warning restore 0618
81             var name = Marshal.PtrToStringAnsi(nativeAuthProperty.Name);
82             var valueBytes = new byte[(int) nativeAuthProperty.ValueLength];
83             Marshal.Copy(nativeAuthProperty.Value, valueBytes, 0, (int)nativeAuthProperty.ValueLength);
84             return AuthProperty.CreateUnsafe(name, valueBytes);
85         }
86 
87         /// <summary>
88         /// grpc_auth_property
89         /// </summary>
90         internal struct NativeAuthProperty
91         {
92             public IntPtr Name;
93             public IntPtr Value;
94             public UIntPtr ValueLength;
95         }
96 
97         /// <summary>
98         /// grpc_auth_property_iterator
99         /// </summary>
100         internal struct NativeAuthPropertyIterator
101         {
102             public IntPtr AuthContext;
103             public UIntPtr Index;
104             public IntPtr Name;
105         }
106     }
107 }
108