[System] xamarin_start_wwan is not available for tvOS and watchOS.
[mono.git] / mcs / class / System / System.Net / WebConnection.cs
index 0f35c49b3e4f35978e5f90a1a25de789657e056f..8c1523ad82484bb59a94c69298e2e3337a0b2c98 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if SECURITY_DEP
-
-#if MONOTOUCH || MONODROID
-using Mono.Security.Protocol.Tls;
-#else
-extern alias MonoSecurity;
-using MonoSecurity::Mono.Security.Protocol.Tls;
-#endif
-
-#endif
-
 using System.IO;
 using System.Collections;
 using System.Net.Sockets;
-using System.Reflection;
 using System.Security.Cryptography.X509Certificates;
 using System.Text;
 using System.Threading;
 using System.Diagnostics;
+using Mono.Net.Security;
 
 namespace System.Net
 {
@@ -93,20 +82,13 @@ namespace System.Net
                NtlmAuthState connect_ntlm_auth_state;
                HttpWebRequest connect_request;
 
-               bool ssl;
-               bool certsAvailable;
                Exception connect_exception;
                static object classLock = new object ();
-               static Type sslStream;
-#if !MONOTOUCH && !MONODROID
-               static PropertyInfo piClient;
-               static PropertyInfo piServer;
-               static PropertyInfo piTrustFailure;
-#endif
+               MonoTlsStream tlsStream;
 
-#if MONOTOUCH
+#if MONOTOUCH && !MONOTOUCH_TV && !MONOTOUCH_WATCH
                [System.Runtime.InteropServices.DllImport ("__Internal")]
-               static extern void monotouch_start_wwan (string uri);
+               static extern void xamarin_start_wwan (string uri);
 #endif
 
                internal ChunkStream ChunkStream {
@@ -170,15 +152,15 @@ namespace System.Net
                                IPHostEntry hostEntry = sPoint.HostEntry;
 
                                if (hostEntry == null) {
-#if MONOTOUCH
-                                       monotouch_start_wwan (sPoint.Address.ToString ());
+#if MONOTOUCH && !MONOTOUCH_TV && !MONOTOUCH_WATCH
+                                       xamarin_start_wwan (sPoint.Address.ToString ());
                                        hostEntry = sPoint.HostEntry;
                                        if (hostEntry == null) {
 #endif
                                                status = sPoint.UsesProxy ? WebExceptionStatus.ProxyNameResolutionFailure :
                                                                            WebExceptionStatus.NameResolutionFailure;
                                                return;
-#if MONOTOUCH
+#if MONOTOUCH && !MONOTOUCH_TV && !MONOTOUCH_WATCH
                                        }
 #endif
                                }
@@ -237,34 +219,6 @@ namespace System.Net
                        }
                }
 
-               static void EnsureSSLStreamAvailable ()
-               {
-                       lock (classLock) {
-                               if (sslStream != null)
-                                       return;
-
-#if NET_2_1 && SECURITY_DEP
-                               sslStream = typeof (HttpsClientStream);
-#else
-                               // HttpsClientStream is an internal glue class in Mono.Security.dll
-                               sslStream = Type.GetType ("Mono.Security.Protocol.Tls.HttpsClientStream, " +
-                                                       Consts.AssemblyMono_Security, false);
-
-                               if (sslStream == null) {
-                                       string msg = "Missing Mono.Security.dll assembly. " +
-                                                       "Support for SSL/TLS is unavailable.";
-
-                                       throw new NotSupportedException (msg);
-                               }
-#endif
-#if !MONOTOUCH && !MONODROID
-                               piClient = sslStream.GetProperty ("SelectedClientCertificate");
-                               piServer = sslStream.GetProperty ("ServerCertificate");
-                               piTrustFailure = sslStream.GetProperty ("TrustFailure");
-#endif
-                       }
-               }
-
                bool CreateTunnel (HttpWebRequest request, Uri connectUri,
                                   Stream stream, out byte[] buffer)
                {
@@ -439,40 +393,31 @@ namespace System.Net
                                NetworkStream serverStream = new NetworkStream (socket, false);
 
                                if (request.Address.Scheme == Uri.UriSchemeHttps) {
-                                       ssl = true;
-                                       EnsureSSLStreamAvailable ();
-                                       if (!reused || nstream == null || nstream.GetType () != sslStream) {
+#if SECURITY_DEP
+                                       if (!reused || nstream == null || tlsStream == null) {
                                                byte [] buffer = null;
                                                if (sPoint.UseConnect) {
                                                        bool ok = CreateTunnel (request, sPoint.Address, serverStream, out buffer);
                                                        if (!ok)
                                                                return false;
                                                }
-#if SECURITY_DEP
-#if MONOTOUCH || MONODROID
-                                               nstream = new HttpsClientStream (serverStream, request.ClientCertificates, request, buffer);
-#else
-                                               object[] args = new object [4] { serverStream,
-                                                       request.ClientCertificates,
-                                                       request, buffer};
-                                               nstream = (Stream) Activator.CreateInstance (sslStream, args);
-#endif
-                                               SslClientStream scs = (SslClientStream) nstream;
-                                               var helper = new ServicePointManager.ChainValidationHelper (request, request.Address.Host);
-                                               scs.ServerCertValidation2 += new CertificateValidationCallback2 (helper.ValidateChain);
-#endif
-                                               certsAvailable = false;
+                                               tlsStream = new MonoTlsStream (request, serverStream);
+                                               nstream = tlsStream.CreateStream (buffer);
                                        }
                                        // we also need to set ServicePoint.Certificate 
                                        // and ServicePoint.ClientCertificate but this can
                                        // only be done later (after handshake - which is
                                        // done only after a read operation).
+#else
+                                       throw new NotSupportedException ();
+#endif
                                } else {
-                                       ssl = false;
                                        nstream = serverStream;
                                }
-                       } catch (Exception) {
-                               if (!request.Aborted)
+                       } catch (Exception ex) {
+                               if (tlsStream != null)
+                                       status = tlsStream.ExceptionStatus;
+                               else if (!request.Aborted)
                                        status = WebExceptionStatus.ConnectFailure;
                                return false;
                        }
@@ -490,11 +435,7 @@ namespace System.Net
 
                        if (e == null) { // At least we now where it comes from
                                try {
-#if TARGET_JVM
-                                       throw new Exception ();
-#else
                                        throw new Exception (new System.Diagnostics.StackTrace ().ToString ());
-#endif
                                } catch (Exception e2) {
                                        e = e2;
                                }
@@ -627,21 +568,6 @@ namespace System.Net
                        return (statusCode >= 200 && statusCode != 204 && statusCode != 304);
                }
 
-               internal void GetCertificates (Stream stream) 
-               {
-                       // here the SSL negotiation have been done
-#if SECURITY_DEP && (MONOTOUCH || MONODROID)
-                       HttpsClientStream s = (stream as HttpsClientStream);
-                       X509Certificate client = s.SelectedClientCertificate;
-                       X509Certificate server = s.ServerCertificate;
-#else
-                       X509Certificate client = (X509Certificate) piClient.GetValue (stream, null);
-                       X509Certificate server = (X509Certificate) piServer.GetValue (stream, null);
-#endif
-                       sPoint.SetCertificates (client, server);
-                       certsAvailable = (server != null);
-               }
-
                internal static void InitRead (object state)
                {
                        WebConnection cnc = (WebConnection) state;
@@ -1071,6 +997,8 @@ namespace System.Net
 
                        Stream s = null;
                        lock (this) {
+                               if (status == WebExceptionStatus.RequestCanceled)
+                                       return true;
                                if (Data.request != request)
                                        throw new ObjectDisposedException (typeof (NetworkStream).FullName);
                                if (nstream == null)
@@ -1144,9 +1072,6 @@ namespace System.Net
 
                        try {
                                s.Write (buffer, offset, size);
-                               // here SSL handshake should have been done
-                               if (ssl && !certsAvailable)
-                                       GetCertificates (s);
                        } catch (Exception e) {
                                err_msg = e.Message;
                                WebExceptionStatus wes = WebExceptionStatus.SendFailure;
@@ -1156,19 +1081,6 @@ namespace System.Net
                                        return false;
                                }
 
-                               // if SSL is in use then check for TrustFailure
-                               if (ssl) {
-#if SECURITY_DEP && (MONOTOUCH || MONODROID)
-                                       HttpsClientStream https = (s as HttpsClientStream);
-                                       if (https.TrustFailure) {
-#else
-                                       if ((bool) piTrustFailure.GetValue (s , null)) {
-#endif
-                                               wes = WebExceptionStatus.TrustFailure;
-                                               msg = "Trust failure";
-                                       }
-                               }
-
                                HandleError (wes, e, msg);
                                return false;
                        }