2 // System.Net.ServicePointManager
\r
5 // Lawrence Pit (loz@cable.a2000.nl)
\r
9 using System.Collections;
\r
10 using System.Collections.Specialized;
\r
11 using System.Configuration;
\r
12 using System.Net.Configuration;
\r
13 using System.Security.Cryptography.X509Certificates;
\r
17 // A service point manager manages service points (duh!).
\r
18 // A service point maintains a list of connections (per scheme + authority).
\r
19 // According to HttpWebRequest.ConnectionGroupName each connection group
\r
20 // creates additional connections. therefor, a service point has a hashtable
\r
21 // of connection groups where each value is a list of connections.
\r
23 // when we need to make an HttpWebRequest, we need to do the following:
\r
24 // 1. find service point, given Uri and Proxy
\r
25 // 2. find connection group, given service point and group name
\r
26 // 3. find free connection in connection group, or create one (if ok due to limits)
\r
27 // 4. lease connection
\r
28 // 5. execute request
\r
29 // 6. when finished, return connection
\r
33 namespace System.Net
\r
35 public class ServicePointManager
\r
37 private static HybridDictionary servicePoints = new HybridDictionary ();
\r
39 // Static properties
\r
41 private static ICertificatePolicy policy = new DefaultCertificatePolicy ();
\r
42 private static int defaultConnectionLimit = DefaultPersistentConnectionLimit;
\r
43 private static int maxServicePointIdleTime = 900000; // 15 minutes
\r
44 private static int maxServicePoints = 0;
45 private static bool _checkCRL = false;
46 #if (NET_1_0 || NET_1_1)
47 private static SecurityProtocolType _securityProtocol = SecurityProtocolType.Ssl3;
49 private static SecurityProtocolType _securityProtocol = SecurityProtocolType.Default;
\r
54 public const int DefaultNonPersistentConnectionLimit = 4;
\r
55 public const int DefaultPersistentConnectionLimit = 2;
\r
57 const string configKey = "system.net/connectionManagement";
\r
58 static ConnectionManagementData manager;
\r
60 static ServicePointManager ()
\r
62 manager = (ConnectionManagementData) ConfigurationSettings.GetConfig (configKey);
\r
65 private ServicePointManager ()
\r
71 public static ICertificatePolicy CertificatePolicy {
\r
72 get { return policy; }
\r
73 set { policy = value; }
\r
77 // we need it for SslClientStream
80 [MonoTODO("CRL checks not implemented")]
83 static bool CheckCertificateRevocationList {
84 get { return _checkCRL; }
85 set { _checkCRL = false; } // TODO - don't yet accept true
88 public static int DefaultConnectionLimit {
\r
89 get { return defaultConnectionLimit; }
\r
92 throw new ArgumentOutOfRangeException ("value");
\r
94 defaultConnectionLimit = value;
\r
98 public static int MaxServicePointIdleTime {
\r
100 return maxServicePointIdleTime;
\r
103 if (value < -2 || value > Int32.MaxValue)
\r
104 throw new ArgumentOutOfRangeException ("value");
\r
105 maxServicePointIdleTime = value;
\r
109 public static int MaxServicePoints {
\r
111 return maxServicePoints;
\r
115 throw new ArgumentException ("value");
\r
117 maxServicePoints = value;
\r
118 RecycleServicePoints ();
\r
123 // we need it for SslClientStream
128 static SecurityProtocolType SecurityProtocol {
129 get { return _securityProtocol; }
130 set { _securityProtocol = value; }
135 public static ServicePoint FindServicePoint (Uri address)
\r
137 return FindServicePoint (address, GlobalProxySelection.Select);
\r
140 public static ServicePoint FindServicePoint (string uriString, IWebProxy proxy)
\r
142 return FindServicePoint (new Uri(uriString), proxy);
\r
145 public static ServicePoint FindServicePoint (Uri address, IWebProxy proxy)
\r
147 if (address == null)
\r
148 throw new ArgumentNullException ("address");
\r
150 RecycleServicePoints ();
\r
152 bool usesProxy = false;
\r
153 if (proxy != null && !proxy.IsBypassed(address)) {
\r
155 address = proxy.GetProxy (address);
\r
156 if (address.Scheme != "http" && address.Scheme != "https")
\r
157 throw new NotSupportedException ("Proxy scheme not supported.");
\r
160 address = new Uri (address.Scheme + "://" + address.Authority);
\r
162 ServicePoint sp = null;
\r
163 lock (servicePoints) {
\r
164 sp = servicePoints [address] as ServicePoint;
\r
168 if (maxServicePoints > 0 && servicePoints.Count >= maxServicePoints)
\r
169 throw new InvalidOperationException ("maximum number of service points reached");
\r
171 string addr = address.ToString ();
\r
172 int limit = (int) manager.GetMaxConnections (addr);
\r
173 sp = new ServicePoint (address, limit, maxServicePointIdleTime);
\r
174 sp.UsesProxy = usesProxy;
\r
175 servicePoints.Add (address, sp);
\r
181 // Internal Methods
\r
183 internal static void RecycleServicePoints ()
\r
185 ArrayList toRemove = new ArrayList ();
\r
186 lock (servicePoints) {
\r
187 IDictionaryEnumerator e = servicePoints.GetEnumerator ();
\r
188 while (e.MoveNext ()) {
\r
189 ServicePoint sp = (ServicePoint) e.Value;
\r
190 if (sp.AvailableForRecycling) {
\r
191 toRemove.Add (e.Key);
\r
195 for (int i = 0; i < toRemove.Count; i++)
\r
196 servicePoints.Remove (toRemove [i]);
\r
198 if (maxServicePoints == 0 || servicePoints.Count <= maxServicePoints)
\r
201 // get rid of the ones with the longest idle time
\r
202 SortedList list = new SortedList (servicePoints.Count);
\r
203 e = servicePoints.GetEnumerator ();
\r
204 while (e.MoveNext ()) {
\r
205 ServicePoint sp = (ServicePoint) e.Value;
\r
206 if (sp.CurrentConnections == 0) {
\r
207 while (list.ContainsKey (sp.IdleSince))
\r
208 sp.IdleSince.AddMilliseconds (1);
\r
209 list.Add (sp.IdleSince, sp.Address);
\r
213 for (int i = 0; i < list.Count && servicePoints.Count > maxServicePoints; i++)
\r
214 servicePoints.Remove (list.GetByIndex (i));
\r