X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem%2FSystem.Net%2FServicePointManager.cs;h=6e23af5ce04be141ac6a10d72171062e106a284c;hb=a0173a7e76ad48889ade46116e516731b170e7c5;hp=d8acf615ab65aee36ddf8c7771270e26b575e71f;hpb=93c35ffe1440538072fb9b95a556768f468f89fb;p=mono.git diff --git a/mcs/class/System/System.Net/ServicePointManager.cs b/mcs/class/System/System.Net/ServicePointManager.cs index d8acf615ab6..6e23af5ce04 100644 --- a/mcs/class/System/System.Net/ServicePointManager.cs +++ b/mcs/class/System/System.Net/ServicePointManager.cs @@ -31,16 +31,24 @@ #if SECURITY_DEP +#if MONOTOUCH +using Mono.Security.Protocol.Tls; +using MSX = Mono.Security.X509; +using Mono.Security.X509.Extensions; +#else extern alias MonoSecurity; - -using System.Text.RegularExpressions; using MonoSecurity::Mono.Security.X509.Extensions; using MonoSecurity::Mono.Security.Protocol.Tls; using MSX = MonoSecurity::Mono.Security.X509; #endif +using System.Text.RegularExpressions; +#endif + using System; +using System.Threading; using System.Collections; +using System.Collections.Generic; using System.Collections.Specialized; using System.Configuration; using System.Net.Configuration; @@ -48,6 +56,7 @@ using System.Security.Cryptography.X509Certificates; using System.Globalization; using System.Net.Security; +using System.Diagnostics; // // notes: @@ -72,10 +81,12 @@ namespace System.Net public class ServicePointManager { class SPKey { Uri uri; // schema/host/port + Uri proxy; bool use_connect; - public SPKey (Uri uri, bool use_connect) { + public SPKey (Uri uri, Uri proxy, bool use_connect) { this.uri = uri; + this.proxy = proxy; this.use_connect = use_connect; } @@ -87,8 +98,16 @@ namespace System.Net get { return use_connect; } } + public bool UsesProxy { + get { return proxy != null; } + } + public override int GetHashCode () { - return uri.GetHashCode () + ((use_connect) ? 1 : 0); + int hash = 23; + hash = hash * 31 + ((use_connect) ? 1 : 0); + hash = hash * 31 + uri.GetHashCode (); + hash = hash * 31 + (proxy != null ? proxy.GetHashCode () : 0); + return hash; } public override bool Equals (object obj) { @@ -97,7 +116,13 @@ namespace System.Net return false; } - return (uri.Equals (other.uri) && other.use_connect == use_connect); + if (!uri.Equals (other.uri)) + return false; + if (use_connect != other.use_connect || UsesProxy != other.UsesProxy) + return false; + if (UsesProxy && !proxy.Equals (other.proxy)) + return false; + return true; } } @@ -107,7 +132,7 @@ namespace System.Net private static ICertificatePolicy policy = new DefaultCertificatePolicy (); private static int defaultConnectionLimit = DefaultPersistentConnectionLimit; - private static int maxServicePointIdleTime = 900000; // 15 minutes + private static int maxServicePointIdleTime = 100000; // 100 seconds private static int maxServicePoints = 0; private static bool _checkCRL = false; private static SecurityProtocolType _securityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls; @@ -304,7 +329,8 @@ namespace System.Net if (address == null) throw new ArgumentNullException ("address"); - RecycleServicePoints (); + if ((servicePoints.Count % 4) == 0) + RecycleServicePoints (); var origAddress = new Uri (address.Scheme + "://" + address.Authority); @@ -324,8 +350,8 @@ namespace System.Net address = new Uri (address.Scheme + "://" + address.Authority); ServicePoint sp = null; + SPKey key = new SPKey (origAddress, usesProxy ? address : null, useConnect); lock (servicePoints) { - SPKey key = new SPKey (origAddress, useConnect); sp = servicePoints [key] as ServicePoint; if (sp != null) return sp; @@ -354,16 +380,23 @@ namespace System.Net // Internal Methods - internal static void RecycleServicePoints () + static void RecycleServicePoints () { - ArrayList toRemove = new ArrayList (); lock (servicePoints) { + var toRemove = new ArrayList (); + var idleList = new SortedDictionary (); IDictionaryEnumerator e = servicePoints.GetEnumerator (); while (e.MoveNext ()) { ServicePoint sp = (ServicePoint) e.Value; - if (sp.AvailableForRecycling) { + DateTime idleSince; + if (sp.CheckAvailableForRecycling (out idleSince)) { toRemove.Add (e.Key); + continue; } + + while (idleList.ContainsKey (idleSince)) + idleSince = idleSince.AddMilliseconds (1); + idleList.Add (idleSince, sp); } for (int i = 0; i < toRemove.Count; i++) @@ -373,25 +406,18 @@ namespace System.Net return; // get rid of the ones with the longest idle time - SortedList list = new SortedList (servicePoints.Count); - e = servicePoints.GetEnumerator (); - while (e.MoveNext ()) { - ServicePoint sp = (ServicePoint) e.Value; - if (sp.CurrentConnections == 0) { - while (list.ContainsKey (sp.IdleSince)) - sp.IdleSince = sp.IdleSince.AddMilliseconds (1); - list.Add (sp.IdleSince, sp.Address); - } + foreach (var sp in idleList.Values) { + if (servicePoints.Count <= maxServicePoints) + break; + servicePoints.Remove (sp); } - - for (int i = 0; i < list.Count && servicePoints.Count > maxServicePoints; i++) - servicePoints.Remove (list.GetByIndex (i)); } } #if SECURITY_DEP internal class ChainValidationHelper { object sender; string host; + RemoteCertificateValidationCallback cb; #if !MONOTOUCH static bool is_macosx = System.IO.File.Exists (OSX509Certificates.SecurityLibrary); @@ -410,19 +436,19 @@ namespace System.Net } #endif - public ChainValidationHelper (object sender) + public ChainValidationHelper (object sender, string hostName) { this.sender = sender; + host = hostName; } - public string Host { + public RemoteCertificateValidationCallback ServerCertificateValidationCallback { get { - if (host == null && sender is HttpWebRequest) - host = ((HttpWebRequest) sender).Address.Host; - return host; + if (cb == null) + cb = ServicePointManager.ServerCertificateValidationCallback; + return cb; } - - set { host = value; } + set { cb = value; } } // Used when the obsolete ICertificatePolicy is set to DefaultCertificatePolicy @@ -435,7 +461,6 @@ namespace System.Net return null; ICertificatePolicy policy = ServicePointManager.CertificatePolicy; - RemoteCertificateValidationCallback cb = ServicePointManager.ServerCertificateValidationCallback; X509Certificate2 leaf = new X509Certificate2 (certs [0].RawData); int status11 = 0; // Error code passed to the obsolete ICertificatePolicy callback @@ -448,7 +473,7 @@ namespace System.Net // the certificates that the server provided (which generally does not include the root) so, only // if there's a user callback, we'll create the X509Chain but won't build it // ref: https://bugzilla.xamarin.com/show_bug.cgi?id=7245 - if (cb != null) { + if (ServerCertificateValidationCallback != null) { #endif chain = new X509Chain (); chain.ChainPolicy = new X509ChainPolicy (); @@ -478,7 +503,7 @@ namespace System.Net status11 = -2146762490; //CERT_E_PURPOSE 0x800B0106 } - if (!CheckServerIdentity (certs [0], Host)) { + if (!CheckServerIdentity (certs [0], host)) { errors |= SslPolicyErrors.RemoteCertificateNameMismatch; status11 = -2146762481; // CERT_E_CN_NO_MATCH 0x800B010F } @@ -488,7 +513,7 @@ namespace System.Net // Ideally we should return the SecTrustResult OSX509Certificates.SecTrustResult trustResult = OSX509Certificates.SecTrustResult.Deny; try { - trustResult = OSX509Certificates.TrustEvaluateSsl (certs, Host); + trustResult = OSX509Certificates.TrustEvaluateSsl (certs, host); // We could use the other values of trustResult to pass this extra information // to the .NET 2 callback for values like SecTrustResult.Confirm result = (trustResult == OSX509Certificates.SecTrustResult.Proceed || @@ -510,7 +535,7 @@ namespace System.Net } #endif -#if MONODROID +#if MONODROID && SECURITY_DEP result = AndroidPlatform.TrustEvaluateSsl (certs, sender, leaf, chain, errors); if (result) { // chain.Build() + GetErrorsFromChain() (above) will ALWAYS fail on @@ -534,8 +559,8 @@ namespace System.Net user_denied = !result && !(policy is DefaultCertificatePolicy); } // If there's a 2.0 callback, it takes precedence - if (cb != null) { - result = cb (sender, leaf, chain, errors); + if (ServerCertificateValidationCallback != null) { + result = ServerCertificateValidationCallback (sender, leaf, chain, errors); user_denied = !result; } return new ValidationResult (result, user_denied, status11);