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.Text; 19 20 namespace Grpc.Core.Internal 21 { 22 /// <summary> 23 /// grpc_metadata_array from <c>grpc/grpc.h</c> 24 /// </summary> 25 internal class MetadataArraySafeHandle : SafeHandleZeroIsInvalid 26 { 27 static readonly NativeMethods Native = NativeMethods.Get(); 28 MetadataArraySafeHandle()29 private MetadataArraySafeHandle() 30 { 31 } 32 Create(Metadata metadata)33 public static MetadataArraySafeHandle Create(Metadata metadata) 34 { 35 if (metadata.Count == 0) 36 { 37 return new MetadataArraySafeHandle(); 38 } 39 40 // TODO(jtattermusch): we might wanna check that the metadata is readonly 41 var metadataArray = Native.grpcsharp_metadata_array_create(new UIntPtr((ulong)metadata.Count)); 42 for (int i = 0; i < metadata.Count; i++) 43 { 44 var valueBytes = metadata[i].GetSerializedValueUnsafe(); 45 Native.grpcsharp_metadata_array_add(metadataArray, metadata[i].Key, valueBytes, new UIntPtr((ulong)valueBytes.Length)); 46 } 47 return metadataArray; 48 } 49 50 /// <summary> 51 /// Reads metadata from pointer to grpc_metadata_array 52 /// </summary> ReadMetadataFromPtrUnsafe(IntPtr metadataArray)53 public static Metadata ReadMetadataFromPtrUnsafe(IntPtr metadataArray) 54 { 55 if (metadataArray == IntPtr.Zero) 56 { 57 return null; 58 } 59 60 ulong count = Native.grpcsharp_metadata_array_count(metadataArray).ToUInt64(); 61 62 var metadata = new Metadata(); 63 for (ulong i = 0; i < count; i++) 64 { 65 var index = new UIntPtr(i); 66 UIntPtr keyLen; 67 IntPtr keyPtr = Native.grpcsharp_metadata_array_get_key(metadataArray, index, out keyLen); 68 int keyLen32 = checked((int)keyLen.ToUInt32()); 69 string key = WellKnownStrings.TryIdentify(keyPtr, keyLen32) 70 ?? Marshal.PtrToStringAnsi(keyPtr, keyLen32); 71 UIntPtr valueLen; 72 IntPtr valuePtr = Native.grpcsharp_metadata_array_get_value(metadataArray, index, out valueLen); 73 int len32 = checked((int)valueLen.ToUInt64()); 74 metadata.Add(Metadata.Entry.CreateUnsafe(key, valuePtr, len32)); 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