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