1 // 2 // MonoBtlsObject.cs 3 // 4 // Author: 5 // Martin Baulig <martin.baulig@xamarin.com> 6 // 7 // Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com) 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining a copy 10 // of this software and associated documentation files (the "Software"), to deal 11 // in the Software without restriction, including without limitation the rights 12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 // copies of the Software, and to permit persons to whom the Software is 14 // furnished to do so, subject to the following conditions: 15 // 16 // The above copyright notice and this permission notice shall be included in 17 // all copies or substantial portions of the Software. 18 // 19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 // THE SOFTWARE. 26 #if SECURITY_DEP && MONO_FEATURE_BTLS 27 using System; 28 using System.Threading; 29 using System.Runtime.InteropServices; 30 using System.Runtime.CompilerServices; 31 32 namespace Mono.Btls 33 { 34 abstract class MonoBtlsObject : IDisposable 35 { 36 internal const string BTLS_DYLIB = "libmono-btls-shared"; 37 MonoBtlsObject(MonoBtlsHandle handle)38 internal MonoBtlsObject (MonoBtlsHandle handle) 39 { 40 this.handle = handle; 41 } 42 43 protected internal abstract class MonoBtlsHandle : SafeHandle 44 { MonoBtlsHandle()45 internal MonoBtlsHandle () 46 : base (IntPtr.Zero, true) 47 { 48 } 49 MonoBtlsHandle(IntPtr handle, bool ownsHandle)50 internal MonoBtlsHandle (IntPtr handle, bool ownsHandle) 51 : base (handle, ownsHandle) 52 { 53 } 54 55 public override bool IsInvalid { 56 get { return handle == IntPtr.Zero; } 57 } 58 } 59 60 internal MonoBtlsHandle Handle { 61 get { 62 CheckThrow (); 63 return handle; 64 } 65 } 66 67 public bool IsValid { 68 get { return handle != null && !handle.IsInvalid; } 69 } 70 71 MonoBtlsHandle handle; 72 Exception lastError; 73 CheckThrow()74 protected void CheckThrow () 75 { 76 if (lastError != null) 77 throw lastError; 78 if (handle == null || handle.IsInvalid) 79 throw new ObjectDisposedException ("MonoBtlsSsl"); 80 } 81 SetException(Exception ex)82 protected Exception SetException (Exception ex) 83 { 84 if (lastError == null) 85 lastError = ex; 86 return ex; 87 } 88 CheckError(bool ok, [CallerMemberName] string callerName = null)89 protected void CheckError (bool ok, [CallerMemberName] string callerName = null) 90 { 91 if (!ok) { 92 if (callerName != null) 93 throw new MonoBtlsException ("{0}.{1} failed.", GetType ().Name, callerName); 94 else 95 throw new MonoBtlsException (); 96 } 97 98 } 99 CheckError(int ret, [CallerMemberName] string callerName = null)100 protected void CheckError (int ret, [CallerMemberName] string callerName = null) 101 { 102 CheckError (ret == 1, callerName); 103 } 104 CheckLastError([CallerMemberName] string callerName = null)105 protected internal void CheckLastError ([CallerMemberName] string callerName = null) 106 { 107 var error = Interlocked.Exchange (ref lastError, null); 108 if (error == null) 109 return; 110 111 string message; 112 if (callerName != null) 113 message = string.Format ("Caught unhandled exception in {0}.{1}.", GetType ().Name, callerName); 114 else 115 message = string.Format ("Caught unhandled exception."); 116 throw new MonoBtlsException (message, error); 117 } 118 119 [DllImport (BTLS_DYLIB)] mono_btls_free(IntPtr data)120 extern static void mono_btls_free (IntPtr data); 121 FreeDataPtr(IntPtr data)122 protected void FreeDataPtr (IntPtr data) 123 { 124 mono_btls_free (data); 125 } 126 Close()127 protected virtual void Close () 128 { 129 } 130 Dispose(bool disposing)131 protected void Dispose (bool disposing) 132 { 133 if (disposing) { 134 try { 135 if (handle != null) { 136 Close (); 137 handle.Dispose (); 138 handle = null; 139 } 140 } finally { 141 var disposedExc = new ObjectDisposedException (GetType ().Name); 142 Interlocked.CompareExchange (ref lastError, disposedExc, null); 143 } 144 } 145 } 146 Dispose()147 public void Dispose () 148 { 149 Dispose (true); 150 GC.SuppressFinalize (this); 151 } 152 ~MonoBtlsObject()153 ~MonoBtlsObject () 154 { 155 Dispose (false); 156 } 157 } 158 } 159 #endif 160