1 #region Copyright notice and license 2 // Copyright 2015 gRPC authors. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 #endregion 16 using System; 17 using System.Runtime.InteropServices; 18 using System.Threading.Tasks; 19 using Grpc.Core.Profiling; 20 21 namespace Grpc.Core.Internal 22 { 23 /// <summary> 24 /// grpc_metadata_array from <c>grpc/grpc.h</c> 25 /// </summary> 26 internal class MetadataArraySafeHandle : SafeHandleZeroIsInvalid 27 { 28 static readonly NativeMethods Native = NativeMethods.Get(); 29 MetadataArraySafeHandle()30 private MetadataArraySafeHandle() 31 { 32 } 33 Create(Metadata metadata)34 public static MetadataArraySafeHandle Create(Metadata metadata) 35 { 36 if (metadata.Count == 0) 37 { 38 return new MetadataArraySafeHandle(); 39 } 40 41 // TODO(jtattermusch): we might wanna check that the metadata is readonly 42 var metadataArray = Native.grpcsharp_metadata_array_create(new UIntPtr((ulong)metadata.Count)); 43 for (int i = 0; i < metadata.Count; i++) 44 { 45 var valueBytes = metadata[i].GetSerializedValueUnsafe(); 46 Native.grpcsharp_metadata_array_add(metadataArray, metadata[i].Key, valueBytes, new UIntPtr((ulong)valueBytes.Length)); 47 } 48 return metadataArray; 49 } 50 51 /// <summary> 52 /// Reads metadata from pointer to grpc_metadata_array 53 /// </summary> ReadMetadataFromPtrUnsafe(IntPtr metadataArray)54 public static Metadata ReadMetadataFromPtrUnsafe(IntPtr metadataArray) 55 { 56 if (metadataArray == IntPtr.Zero) 57 { 58 return null; 59 } 60 61 ulong count = Native.grpcsharp_metadata_array_count(metadataArray).ToUInt64(); 62 63 var metadata = new Metadata(); 64 for (ulong i = 0; i < count; i++) 65 { 66 var index = new UIntPtr(i); 67 UIntPtr keyLen; 68 IntPtr keyPtr = Native.grpcsharp_metadata_array_get_key(metadataArray, index, out keyLen); 69 string key = Marshal.PtrToStringAnsi(keyPtr, (int)keyLen.ToUInt32()); 70 UIntPtr valueLen; 71 IntPtr valuePtr = Native.grpcsharp_metadata_array_get_value(metadataArray, index, out valueLen); 72 var bytes = new byte[valueLen.ToUInt64()]; 73 Marshal.Copy(valuePtr, bytes, 0, bytes.Length); 74 metadata.Add(Metadata.Entry.CreateUnsafe(key, bytes)); 75 } 76 return metadata; 77 } 78 79 internal IntPtr Handle 80 { 81 get 82 { 83 return handle; 84 } 85 } 86 ReleaseHandle()87 protected override bool ReleaseHandle() 88 { 89 Native.grpcsharp_metadata_array_destroy_full(handle); 90 return true; 91 } 92 } 93 } 94