Merge pull request #5428 from kumpera/wasm-support-p2
[mono.git] / mcs / class / System / Mono.AppleTls / AppleTlsContext.cs
index 4fa1730df2a10ffc33fc7d9a5a792259737b8db6..0cc69e47648db2ed9fc45b7bc8af47bd83713b5d 100644 (file)
@@ -44,7 +44,7 @@ namespace Mono.AppleTls
 
                GCHandle handle;
                IntPtr context;
-               IntPtr connectionId;
+
                SslReadFunc readFunc;
                SslWriteFunc writeFunc;
 
@@ -73,8 +73,7 @@ namespace Mono.AppleTls
                        : base (parent, serverMode, targetHost, enabledProtocols,
                                serverCertificate, clientCertificates, askForClientCert)
                {
-                       handle = GCHandle.Alloc (this);
-                       connectionId = GCHandle.ToIntPtr (handle);
+                       handle = GCHandle.Alloc (this, GCHandleType.Weak);
                        readFunc = NativeReadCallback;
                        writeFunc = NativeWriteCallback;
 
@@ -96,12 +95,6 @@ namespace Mono.AppleTls
                        get { return !disposed && context != IntPtr.Zero; }
                }
 
-               [System.Diagnostics.Conditional ("APPLE_TLS_DEBUG")]
-               protected new void Debug (string message, params object[] args)
-               {
-                       Console.Error.WriteLine ("MobileTlsStream({0}): {1}", Parent.ID, string.Format (message, args));
-               }
-
                void CheckStatusAndThrow (SslStatus status, params SslStatus[] acceptable)
                {
                        var last = Interlocked.Exchange (ref lastException, null);
@@ -235,32 +228,41 @@ namespace Mono.AppleTls
                         * 
                         */
 
-                       var trust = GetPeerTrust (!IsServer);
-                       X509CertificateCollection certificates;
+                       bool ok;
+                       SecTrust trust = null;
+                       X509CertificateCollection certificates = null;
+
+                       try {
+                               trust = GetPeerTrust (!IsServer);
 
-                       if (trust == null || trust.Count == 0) {
-                               remoteCertificate = null;
-                               if (!IsServer)
-                                       throw new TlsException (AlertDescription.CertificateUnknown);
-                               certificates = null;
-                       } else {
-                               if (trust.Count > 1)
-                                       Debug ("WARNING: Got multiple certificates in SecTrust!");
+                               if (trust == null || trust.Count == 0) {
+                                       remoteCertificate = null;
+                                       if (!IsServer)
+                                               throw new TlsException (AlertDescription.CertificateUnknown);
+                                       certificates = null;
+                               } else {
+                                       if (trust.Count > 1)
+                                               Debug ("WARNING: Got multiple certificates in SecTrust!");
 
-                               certificates = new X509CertificateCollection ();
-                               for (int i = 0; i < trust.Count; i++)
-                                       certificates.Add (trust [(IntPtr)i].ToX509Certificate ());
+                                       certificates = new X509CertificateCollection ();
+                                       for (int i = 0; i < trust.Count; i++)
+                                               certificates.Add (trust.GetCertificate (i));
 
-                               remoteCertificate = certificates [0];
-                               Debug ("Got peer trust: {0}", remoteCertificate);
-                       }
+                                       remoteCertificate = new X509Certificate (certificates [0]);
+                                       Debug ("Got peer trust: {0}", remoteCertificate);
+                               }
 
-                       bool ok;
-                       try {
                                ok = ValidateCertificate (certificates);
                        } catch (Exception ex) {
                                Debug ("Certificate validation failed: {0}", ex);
                                throw new TlsException (AlertDescription.CertificateUnknown, "Certificate validation threw exception.");
+                       } finally {
+                               if (trust != null)
+                                       trust.Dispose ();
+                               if (certificates != null) {
+                                       for (int i = 0; i < certificates.Count; i++)
+                                               certificates [i].Dispose ();
+                               }
                        }
 
                        if (!ok)
@@ -274,7 +276,7 @@ namespace Mono.AppleTls
                        var result = SSLSetIOFuncs (Handle, readFunc, writeFunc);
                        CheckStatusAndThrow (result);
 
-                       result = SSLSetConnection (Handle, connectionId);
+                       result = SSLSetConnection (Handle, GCHandle.ToIntPtr (handle));
                        CheckStatusAndThrow (result);
 
                        if ((EnabledProtocols & SSA.SslProtocols.Tls) != 0)
@@ -291,11 +293,6 @@ namespace Mono.AppleTls
                        else
                                MaxProtocol = SslProtocol.Tls_1_0;
 
-#if APPLE_TLS_DEBUG
-                       foreach (var c in GetSupportedCiphers ())
-                               Debug ("  {0} SslCipherSuite.{1} {2:x} {3}", IsServer ? "Server" : "Client", c, (int)c, (CipherSuiteCode)c);
-#endif
-
                        if (Settings != null && Settings.EnabledCiphers != null) {
                                SslCipherSuite [] ciphers = new SslCipherSuite [Settings.EnabledCiphers.Length];
                                for (int i = 0 ; i < Settings.EnabledCiphers.Length; ++i)
@@ -665,7 +662,7 @@ namespace Mono.AppleTls
                                if (value == IntPtr.Zero)
                                        throw new TlsException (AlertDescription.CertificateUnknown);
                        }
-                       return (value == IntPtr.Zero) ? null : new SecTrust (value);
+                       return (value == IntPtr.Zero) ? null : new SecTrust (value, true);
                }
 
                #endregion
@@ -684,18 +681,19 @@ namespace Mono.AppleTls
                [Mono.Util.MonoPInvokeCallback (typeof (SslReadFunc))]
                static SslStatus NativeReadCallback (IntPtr ptr, IntPtr data, ref IntPtr dataLength)
                {
-                       var handle = GCHandle.FromIntPtr (ptr);
-                       if (!handle.IsAllocated)
-                               return SslStatus.Internal;
+                       AppleTlsContext context = null;
+                       try {
+                               var weakHandle = GCHandle.FromIntPtr (ptr);
+                               if (!weakHandle.IsAllocated)
+                                       return SslStatus.Internal;
 
-                       var context = (AppleTlsContext) handle.Target;
-                       if (context.disposed)
-                               return SslStatus.ClosedAbort;
+                               context = (AppleTlsContext) weakHandle.Target;
+                               if (context == null || context.disposed)
+                                       return SslStatus.ClosedAbort;
 
-                       try {
                                return context.NativeReadCallback (data, ref dataLength);
                        } catch (Exception ex) {
-                               if (context.lastException == null)
+                               if (context != null && context.lastException == null)
                                        context.lastException = ex;
                                return SslStatus.Internal;
                        }
@@ -704,18 +702,19 @@ namespace Mono.AppleTls
                [Mono.Util.MonoPInvokeCallback (typeof (SslWriteFunc))]
                static SslStatus NativeWriteCallback (IntPtr ptr, IntPtr data, ref IntPtr dataLength)
                {
-                       var handle = GCHandle.FromIntPtr (ptr);
-                       if (!handle.IsAllocated)
-                               return SslStatus.Internal;
+                       AppleTlsContext context = null;
+                       try {
+                               var weakHandle = GCHandle.FromIntPtr (ptr);
+                               if (!weakHandle.IsAllocated)
+                                       return SslStatus.Internal;
 
-                       var context = (AppleTlsContext) handle.Target;
-                       if (context.disposed)
-                               return SslStatus.ClosedAbort;
+                               context = (AppleTlsContext) weakHandle.Target;
+                               if (context == null || context.disposed)
+                                       return SslStatus.ClosedAbort;
 
-                       try {
                                return context.NativeWriteCallback (data, ref dataLength);
                        } catch (Exception ex) {
-                               if (context.lastException == null)
+                               if (context != null && context.lastException == null)
                                        context.lastException = ex;
                                return SslStatus.Internal;
                        }
@@ -776,7 +775,7 @@ namespace Mono.AppleTls
                [DllImport (SecurityLibrary)]
                extern unsafe static /* OSStatus */ SslStatus SSLRead (/* SSLContextRef */ IntPtr context, /* const void* */ byte* data, /* size_t */ IntPtr dataLength, /* size_t* */ out IntPtr processed);
 
-               public override unsafe int Read (byte[] buffer, int offset, int count, out bool wantMore)
+               public override unsafe (int ret, bool wantMore) Read (byte[] buffer, int offset, int count)
                {
                        if (Interlocked.Exchange (ref pendingIO, 1) == 1)
                                throw new InvalidOperationException ();
@@ -800,13 +799,12 @@ namespace Mono.AppleTls
                                         * when the first inner Read() returns 0.  MobileAuthenticatedStream.InnerRead() attempts
                                         * to distinguish between a graceful close and abnormal termination of connection.
                                         */
-                                       wantMore = false;
-                                       return 0;
+                                       return (0, false);
                                }
 
                                CheckStatusAndThrow (status, SslStatus.WouldBlock, SslStatus.ClosedGraceful);
-                               wantMore = status == SslStatus.WouldBlock;
-                               return (int)processed;
+                               var wantMore = status == SslStatus.WouldBlock;
+                               return ((int)processed, wantMore);
                        } catch (Exception ex) {
                                Debug ("Read error: {0}", ex);
                                throw;
@@ -818,7 +816,7 @@ namespace Mono.AppleTls
                [DllImport (SecurityLibrary)]
                extern unsafe static /* OSStatus */ SslStatus SSLWrite (/* SSLContextRef */ IntPtr context, /* const void* */ byte* data, /* size_t */ IntPtr dataLength, /* size_t* */ out IntPtr processed);
 
-               public override unsafe int Write (byte[] buffer, int offset, int count, out bool wantMore)
+               public override unsafe (int ret, bool wantMore) Write (byte[] buffer, int offset, int count)
                {
                        if (Interlocked.Exchange (ref pendingIO, 1) == 1)
                                throw new InvalidOperationException ();
@@ -838,8 +836,8 @@ namespace Mono.AppleTls
 
                                CheckStatusAndThrow (status, SslStatus.WouldBlock);
 
-                               wantMore = status == SslStatus.WouldBlock;
-                               return (int)processed;
+                               var wantMore = status == SslStatus.WouldBlock;
+                               return ((int)processed, wantMore);
                        } finally {
                                pendingIO = 0;
                        }
@@ -850,24 +848,7 @@ namespace Mono.AppleTls
 
                public override void Shutdown ()
                {
-                       if (Interlocked.Exchange (ref pendingIO, 1) == 1)
-                               throw new InvalidOperationException ();
-
-                       Debug ("Shutdown");
-
-                       lastException = null;
-
-                       try {
-                               if (closed || disposed)
-                                       return;
-
-                               var status = SSLClose (Handle);
-                               Debug ("Shutdown done: {0}", status);
-                               CheckStatusAndThrow (status);
-                       } finally {
-                               closed = true;
-                               pendingIO = 0;
-                       }
+                       closed = true;
                }
 
                #endregion