context: //
  // System.Net.ServicePointManager
  //
  // Authors:
  //   Lawrence Pit (loz@cable.a2000.nl)
  //   Gonzalo Paniagua Javier (gonzalo@novell.com)
  //
  // Copyright (c) 2003-2010 Novell, Inc (http://www.novell.com)
  //
  
  //
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  // 
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  #if SECURITY_DEP
  
  #if MONOTOUCH || MONODROID
  using Mono.Security.Protocol.Tls;
  using MSX = Mono.Security.X509;
  using Mono.Security.X509.Extensions;
  #else
  extern alias MonoSecurity;
  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;
  using System.Security.Cryptography.X509Certificates;
  
  using System.Globalization;
  using System.Net.Security;
  using System.Diagnostics;
  
  //
  // notes:
  // A service point manager manages service points (duh!).
  // A service point maintains a list of connections (per scheme + authority).
  // According to HttpWebRequest.ConnectionGroupName each connection group
  // creates additional connections. therefor, a service point has a hashtable
  // of connection groups where each value is a list of connections.
  // 
  // when we need to make an HttpWebRequest, we need to do the following:
  // 1. find service point, given Uri and Proxy 
  // 2. find connection group, given service point and group name
  // 3. find free connection in connection group, or create one (if ok due to limits)
  // 4. lease connection
  // 5. execute request
  // 6. when finished, return connection
  //
  
  
  namespace System.Net 
  {
  	public partial class ServicePointManager {
  		class SPKey {
  			Uri uri; // schema/host/port
  			Uri proxy;
  			bool use_connect;
  
  			public SPKey (Uri uri, Uri proxy, bool use_connect) {
  				this.uri = uri;
  				this.proxy = proxy;
  				this.use_connect = use_connect;
  			}
  
  			public Uri Uri {
  				get { return uri; }
  			}
  
  			public bool UseConnect {
  				get { return use_connect; }
  			}
  
  			public bool UsesProxy {
  				get { return proxy != null; }
  			}
  
  			public override int GetHashCode () {
  				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) {
  				SPKey other = obj as SPKey;
  				if (obj == null) {
  					return false;
  				}
  
  				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;
  			}
  		}
  
  		private static HybridDictionary servicePoints = new HybridDictionary ();
  		
  		// Static properties
  		
  		private static ICertificatePolicy policy = new DefaultCertificatePolicy ();
  		private static int defaultConnectionLimit = DefaultPersistentConnectionLimit;
  		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;
  
  #if TARGET_JVM
  		static bool expectContinue = false;
  #else
  		static bool expectContinue = true;
  #endif
  		static bool useNagle;
  		static RemoteCertificateValidationCallback server_cert_cb;
  		static bool tcp_keepalive;
  		static int tcp_keepalive_time;
  		static int tcp_keepalive_interval;
  
  		// Fields
  		
  		public const int DefaultNonPersistentConnectionLimit = 4;
  #if MONOTOUCH
  		public const int DefaultPersistentConnectionLimit = 10;
  #else
  		public const int DefaultPersistentConnectionLimit = 2;
  #endif
  
  #if !NET_2_1
  		const string configKey = "system.net/connectionManagement";
  		static ConnectionManagementData manager;
  #endif
  		
  		static ServicePointManager ()
  		{
  #if !NET_2_1
  #if CONFIGURATION_DEP
  			object cfg = ConfigurationManager.GetSection (configKey);
  			ConnectionManagementSection s = cfg as ConnectionManagementSection;
  			if (s != null) {
  				manager = new ConnectionManagementData (null);
  				foreach (ConnectionManagementElement e in s.ConnectionManagement)
  					manager.Add (e.Address, e.MaxConnection);
  
  				defaultConnectionLimit = (int) manager.GetMaxConnections ("*");				
  				return;
  			}
  #endif
  			manager = (ConnectionManagementData) ConfigurationSettings.GetConfig (configKey);
  			if (manager != null) {
  				defaultConnectionLimit = (int) manager.GetMaxConnections ("*");				
  			}
  #endif
  		}
  
  		// Constructors
  		private ServicePointManager ()
  		{
  		}		
  		
  		// Properties
  		
  		[Obsolete ("Use ServerCertificateValidationCallback instead", false)]
  		public static ICertificatePolicy CertificatePolicy {
  			get { return policy; }
  			set { policy = value; }
  		}
  
  		[MonoTODO("CRL checks not implemented")]
  		public static bool CheckCertificateRevocationList {
  			get { return _checkCRL; }
  			set { _checkCRL = false; }	// TODO - don't yet accept true
  		}
  		
  		public static int DefaultConnectionLimit {
  			get { return defaultConnectionLimit; }
  			set { 
  				if (value <= 0)
  					throw new ArgumentOutOfRangeException ("value");
  
  				defaultConnectionLimit = value; 
  #if !NET_2_1
                  if (manager != null)
  					manager.Add ("*", defaultConnectionLimit);
  #endif
  			}
  		}
  
  		static Exception GetMustImplement ()
  		{
  
gt: 			return new NotImplementedException ();