merged Sys.Web.Services 2.0 support in my branch:
[mono.git] / mcs / class / System / System.Net / ServicePoint.cs
1 //
2 // System.Net.ServicePoint
3 //
4 // Authors:
5 //      Lawrence Pit (loz@cable.a2000.nl)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (c) 2002 Lawrence Pit
9 // (c) 2003 Ximian, Inc. (http://www.ximian.com)
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.Collections;
35 using System.Net.Sockets;
36 using System.Security.Cryptography.X509Certificates;
37 using System.Threading;
38
39 namespace System.Net 
40 {
41         public class ServicePoint
42         {
43                 Uri uri;
44                 int connectionLimit;
45                 int maxIdleTime;
46                 int currentConnections;
47                 DateTime idleSince;
48                 Version protocolVersion;
49                 X509Certificate certificate;
50                 X509Certificate clientCertificate;
51                 IPHostEntry host;
52                 bool usesProxy;
53                 Hashtable groups;
54                 bool sendContinue = true;
55                 bool useConnect;
56                 object locker = new object ();
57                 object hostE = new object ();
58 #if NET_1_1
59                 bool useNagle;
60 #endif
61                 
62                 // Constructors
63
64                 internal ServicePoint (Uri uri, int connectionLimit, int maxIdleTime)
65                 {
66                         this.uri = uri;  
67                         this.connectionLimit = connectionLimit;
68                         this.maxIdleTime = maxIdleTime;                 
69                         this.currentConnections = 0;
70                         this.idleSince = DateTime.Now;
71                 }
72                 
73                 // Properties
74                 
75                 public Uri Address {
76                         get { return uri; }
77                 }
78                 
79                 public X509Certificate Certificate {
80                         get { return certificate; }
81                 }
82                 
83                 public X509Certificate ClientCertificate {
84                         get { return clientCertificate; }
85                 }
86                 
87                 public int ConnectionLimit {
88                         get { return connectionLimit; }
89                         set {
90                                 if (value <= 0)
91                                         throw new ArgumentOutOfRangeException ();
92
93                                 connectionLimit = value;
94                         }
95                 }
96                 
97                 public string ConnectionName {
98                         get { return uri.Scheme; }
99                 }
100
101                 public int CurrentConnections {
102                         get {
103                                 return currentConnections;
104                         }
105                 }
106
107                 public DateTime IdleSince {
108                         get {
109                                 return idleSince;
110                         }
111                         internal set {
112                                 lock (locker)
113                                         idleSince = value;
114                         }
115                 }
116                 
117                 public int MaxIdleTime {
118                         get { return maxIdleTime; }
119                         set { 
120                                 if (value < Timeout.Infinite || value > Int32.MaxValue)
121                                         throw new ArgumentOutOfRangeException ();
122                                 this.maxIdleTime = value; 
123                         }
124                 }
125                 
126                 public virtual Version ProtocolVersion {
127                         get { return protocolVersion; }
128                 }
129                 
130                 public bool SupportsPipelining {
131                         get { return HttpVersion.Version11.Equals (protocolVersion); }
132                 }
133
134 #if NET_1_1
135                 public bool Expect100Continue {
136                         get { return SendContinue; }
137                         set { SendContinue = value; }
138                 }
139
140                 [MonoTODO ("Use me")]
141                 public bool UseNagleAlgorithm {
142                         get { return useNagle; }
143                         set { useNagle = value; }
144                 }
145 #endif
146
147                 internal bool SendContinue {
148                         get { return sendContinue &&
149                                      (protocolVersion == null || protocolVersion == HttpVersion.Version11); }
150                         set { sendContinue = value; }
151                 }
152                 // Methods
153                 
154                 public override int GetHashCode() 
155                 {
156                         return base.GetHashCode ();
157                 }
158                 
159                 // Internal Methods
160
161                 internal bool UsesProxy {
162                         get { return usesProxy; }
163                         set { usesProxy = value; }
164                 }
165
166                 internal bool UseConnect {
167                         get { return useConnect; }
168                         set { useConnect = value; }
169                 }
170
171                 internal bool AvailableForRecycling {
172                         get { 
173                                 return CurrentConnections == 0
174                                     && maxIdleTime != Timeout.Infinite
175                                     && DateTime.Now >= IdleSince.AddMilliseconds (maxIdleTime);
176                         }
177                 }
178
179                 internal Hashtable Groups {
180                         get {
181                                 if (groups == null)
182                                         groups = new Hashtable ();
183
184                                 return groups;
185                         }
186                 }
187
188                 internal IPHostEntry HostEntry
189                 {
190                         get {
191                                 lock (hostE) {
192                                         if (host != null)
193                                                 return host;
194
195                                         string uriHost = uri.Host;
196
197                                         // There is no need to do DNS resolution on literal IP addresses
198                                         if (uri.HostNameType == UriHostNameType.IPv6 ||
199                                                 uri.HostNameType == UriHostNameType.IPv4) {
200
201                                                 if (uri.HostNameType == UriHostNameType.IPv6) {
202                                                         // Remove square brackets
203                                                         uriHost = uriHost.Substring(1,uriHost.Length-2);
204                                                 }
205
206                                                 // Creates IPHostEntry
207                                                 host = new IPHostEntry();
208                                                 host.AddressList = new IPAddress[] { IPAddress.Parse(uriHost) };
209
210                                                 return host;
211                                         }
212
213                                         // Try DNS resolution on host names
214                                         try  {
215                                                 host = Dns.GetHostByName (uriHost);
216                                         } 
217                                         catch {
218                                                 return null;
219                                         }
220                                 }
221
222                                 return host;
223                         }
224                 }
225
226                 internal void SetVersion (Version version)
227                 {
228                         protocolVersion = version;
229                 }
230 #if !TARGET_JVM
231                 WebConnectionGroup GetConnectionGroup (string name)
232                 {
233                         if (name == null)
234                                 name = "";
235
236                         WebConnectionGroup group = Groups [name] as WebConnectionGroup;
237                         if (group != null)
238                                 return group;
239
240                         group = new WebConnectionGroup (this, name);
241                         Groups [name] = group;
242                         return group;
243                 }
244
245                 internal EventHandler SendRequest (HttpWebRequest request, string groupName)
246                 {
247                         WebConnection cnc;
248                         
249                         lock (locker) {
250                                 WebConnectionGroup cncGroup = GetConnectionGroup (groupName);
251                                 cnc = cncGroup.GetConnection ();
252                         }
253                         
254                         return cnc.SendRequest (request);
255                 }
256 #endif
257                 internal void IncrementConnection ()
258                 {
259                         lock (locker) {
260                                 currentConnections++;
261                                 idleSince = DateTime.Now.AddMilliseconds (1000000);
262                         }
263                 }
264
265                 internal void DecrementConnection ()
266                 {
267                         lock (locker) {
268                                 currentConnections--;
269                                 if (currentConnections == 0)
270                                         idleSince = DateTime.Now;
271                         }
272                 }
273
274                 internal void SetCertificates (X509Certificate client, X509Certificate server) 
275                 {
276                         certificate = server;
277                         clientCertificate = client;
278                 }
279         }
280 }
281