Removed Consoles and ^Ms
[mono.git] / mcs / class / System / System.Net / ServicePointManager.cs
1 //\r
2 // System.Net.ServicePointManager\r
3 //\r
4 // Author:\r
5 //   Lawrence Pit (loz@cable.a2000.nl)\r
6 //\r
7 \r
8 using System;\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
14 \r
15 //\r
16 // notes:\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
22 // \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
30 //\r
31 \r
32 \r
33 namespace System.Net \r
34 {\r
35         public class ServicePointManager\r
36         {\r
37                 private static HybridDictionary servicePoints = new HybridDictionary ();\r
38                 \r
39                 // Static properties\r
40                 \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;
48 #else\r
49                 private static SecurityProtocolType _securityProtocol = SecurityProtocolType.Default;\r
50 #endif
51 \r
52                 // Fields\r
53                 \r
54                 public const int DefaultNonPersistentConnectionLimit = 4;\r
55                 public const int DefaultPersistentConnectionLimit = 2;\r
56 \r
57                 const string configKey = "system.net/connectionManagement";\r
58                 static ConnectionManagementData manager;\r
59                 \r
60                 static ServicePointManager ()\r
61                 {\r
62                         manager = (ConnectionManagementData) ConfigurationSettings.GetConfig (configKey);\r
63                 }\r
64                 // Constructors\r
65                 private ServicePointManager ()\r
66                 {\r
67                 }               \r
68                 \r
69                 // Properties\r
70                 \r
71                 public static ICertificatePolicy CertificatePolicy {\r
72                         get { return policy; }\r
73                         set { policy = value; }\r
74                 }
75
76 #if NET_1_0
77                 // we need it for SslClientStream
78                 internal
79 #else
80                 [MonoTODO("CRL checks not implemented")]
81                 public
82 #endif
83                 static bool CheckCertificateRevocationList {
84                         get { return _checkCRL; }
85                         set { _checkCRL = false; }      // TODO - don't yet accept true
86                 }
87                 \r
88                 public static int DefaultConnectionLimit {\r
89                         get { return defaultConnectionLimit; }\r
90                         set { \r
91                                 if (value <= 0)\r
92                                         throw new ArgumentOutOfRangeException ("value");\r
93 \r
94                                 defaultConnectionLimit = value; \r
95                         }\r
96                 }\r
97                 \r
98                 public static int MaxServicePointIdleTime {\r
99                         get { \r
100                                 return maxServicePointIdleTime;\r
101                         }\r
102                         set { \r
103                                 if (value < -2 || value > Int32.MaxValue)\r
104                                         throw new ArgumentOutOfRangeException ("value");\r
105                                 maxServicePointIdleTime = value;\r
106                         }\r
107                 }\r
108                 \r
109                 public static int MaxServicePoints {\r
110                         get { \r
111                                 return maxServicePoints; \r
112                         }\r
113                         set {  \r
114                                 if (value < 0)\r
115                                         throw new ArgumentException ("value");                          \r
116 \r
117                                 maxServicePoints = value;\r
118                                 RecycleServicePoints ();\r
119                         }\r
120                 }
121
122 #if NET_1_0
123                 // we need it for SslClientStream
124                 internal
125 #else
126                 public
127 #endif
128                 static SecurityProtocolType SecurityProtocol {
129                         get { return _securityProtocol; }
130                         set { _securityProtocol = value; }
131                 }\r
132                 \r
133                 // Methods\r
134                 \r
135                 public static ServicePoint FindServicePoint (Uri address) \r
136                 {\r
137                         return FindServicePoint (address, GlobalProxySelection.Select);\r
138                 }\r
139                 \r
140                 public static ServicePoint FindServicePoint (string uriString, IWebProxy proxy)\r
141                 {\r
142                         return FindServicePoint (new Uri(uriString), proxy);\r
143                 }\r
144                 \r
145                 public static ServicePoint FindServicePoint (Uri address, IWebProxy proxy)\r
146                 {\r
147                         if (address == null)\r
148                                 throw new ArgumentNullException ("address");\r
149 \r
150                         RecycleServicePoints ();\r
151                         \r
152                         bool usesProxy = false;\r
153                         if (proxy != null && !proxy.IsBypassed(address)) {\r
154                                 usesProxy = true;\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
158                         } \r
159 \r
160                         address = new Uri (address.Scheme + "://" + address.Authority);\r
161                         \r
162                         ServicePoint sp = null;\r
163                         lock (servicePoints) {\r
164                                 sp = servicePoints [address] as ServicePoint;\r
165                                 if (sp != null)\r
166                                         return sp;\r
167 \r
168                                 if (maxServicePoints > 0 && servicePoints.Count >= maxServicePoints)\r
169                                         throw new InvalidOperationException ("maximum number of service points reached");\r
170 \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
176                         }\r
177                         \r
178                         return sp;\r
179                 }\r
180                 \r
181                 // Internal Methods\r
182 \r
183                 internal static void RecycleServicePoints ()\r
184                 {\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
192                                         }\r
193                                 }\r
194                                 \r
195                                 for (int i = 0; i < toRemove.Count; i++) \r
196                                         servicePoints.Remove (toRemove [i]);\r
197 \r
198                                 if (maxServicePoints == 0 || servicePoints.Count <= maxServicePoints)\r
199                                         return;\r
200 \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
210                                         }\r
211                                 }\r
212                                 \r
213                                 for (int i = 0; i < list.Count && servicePoints.Count > maxServicePoints; i++)\r
214                                         servicePoints.Remove (list.GetByIndex (i));\r
215                         }\r
216                 }\r
217         }\r
218 }\r