2 // System.Net.ServicePoint
5 // Lawrence Pit (loz@cable.a2000.nl)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 // (c) 2002 Lawrence Pit
9 // (c) 2003 Ximian, Inc. (http://www.ximian.com)
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:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
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.
34 using System.Collections;
35 using System.Net.Sockets;
36 using System.Security.Cryptography.X509Certificates;
37 using System.Threading;
41 public class ServicePoint
46 int currentConnections;
48 Version protocolVersion;
49 X509Certificate certificate;
50 X509Certificate clientCertificate;
54 bool sendContinue = true;
56 object locker = new object ();
57 object hostE = new object ();
62 BindIPEndPoint endPointCallback = null;
67 internal ServicePoint (Uri uri, int connectionLimit, int maxIdleTime)
70 this.connectionLimit = connectionLimit;
71 this.maxIdleTime = maxIdleTime;
72 this.currentConnections = 0;
73 this.idleSince = DateTime.Now;
83 static Exception GetMustImplement ()
85 return new NotImplementedException ();
88 public BindIPEndPoint BindIPEndPointDelegate
90 get { return endPointCallback; }
91 set { endPointCallback = value; }
95 public X509Certificate Certificate {
96 get { return certificate; }
99 public X509Certificate ClientCertificate {
100 get { return clientCertificate; }
105 public int ConnectionLeaseTimeout
108 throw GetMustImplement ();
111 throw GetMustImplement ();
116 public int ConnectionLimit {
117 get { return connectionLimit; }
120 throw new ArgumentOutOfRangeException ();
122 connectionLimit = value;
126 public string ConnectionName {
127 get { return uri.Scheme; }
130 public int CurrentConnections {
132 return currentConnections;
136 public DateTime IdleSince {
146 public int MaxIdleTime {
147 get { return maxIdleTime; }
149 if (value < Timeout.Infinite || value > Int32.MaxValue)
150 throw new ArgumentOutOfRangeException ();
151 this.maxIdleTime = value;
155 public virtual Version ProtocolVersion {
156 get { return protocolVersion; }
161 public int ReceiveBufferSize
164 throw GetMustImplement ();
167 throw GetMustImplement ();
172 public bool SupportsPipelining {
173 get { return HttpVersion.Version11.Equals (protocolVersion); }
177 public bool Expect100Continue {
178 get { return SendContinue; }
179 set { SendContinue = value; }
182 [MonoTODO ("Use me")]
183 public bool UseNagleAlgorithm {
184 get { return useNagle; }
185 set { useNagle = value; }
189 internal bool SendContinue {
190 get { return sendContinue &&
191 (protocolVersion == null || protocolVersion == HttpVersion.Version11); }
192 set { sendContinue = value; }
197 public override int GetHashCode()
199 return base.GetHashCode ();
205 internal bool UsesProxy {
206 get { return usesProxy; }
207 set { usesProxy = value; }
210 internal bool UseConnect {
211 get { return useConnect; }
212 set { useConnect = value; }
215 internal bool AvailableForRecycling {
217 return CurrentConnections == 0
218 && maxIdleTime != Timeout.Infinite
219 && DateTime.Now >= IdleSince.AddMilliseconds (maxIdleTime);
223 internal Hashtable Groups {
226 groups = new Hashtable ();
232 internal IPHostEntry HostEntry
239 string uriHost = uri.Host;
241 // There is no need to do DNS resolution on literal IP addresses
242 if (uri.HostNameType == UriHostNameType.IPv6 ||
243 uri.HostNameType == UriHostNameType.IPv4) {
245 if (uri.HostNameType == UriHostNameType.IPv6) {
246 // Remove square brackets
247 uriHost = uriHost.Substring(1,uriHost.Length-2);
250 // Creates IPHostEntry
251 host = new IPHostEntry();
252 host.AddressList = new IPAddress[] { IPAddress.Parse(uriHost) };
257 // Try DNS resolution on host names
259 host = Dns.GetHostByName (uriHost);
270 internal void SetVersion (Version version)
272 protocolVersion = version;
274 #if !TARGET_JVM && !NET_2_1
275 WebConnectionGroup GetConnectionGroup (string name)
280 WebConnectionGroup group = Groups [name] as WebConnectionGroup;
284 group = new WebConnectionGroup (this, name);
285 Groups [name] = group;
289 internal EventHandler SendRequest (HttpWebRequest request, string groupName)
294 WebConnectionGroup cncGroup = GetConnectionGroup (groupName);
295 cnc = cncGroup.GetConnection (request);
298 return cnc.SendRequest (request);
302 [MonoNotSupported ("")]
303 public bool CloseConnectionGroup (string connectionGroupName)
305 throw new NotImplementedException ();
309 internal void IncrementConnection ()
312 currentConnections++;
313 idleSince = DateTime.Now.AddMilliseconds (1000000);
317 internal void DecrementConnection ()
320 currentConnections--;
321 if (currentConnections == 0)
322 idleSince = DateTime.Now;
326 internal void SetCertificates (X509Certificate client, X509Certificate server)
328 certificate = server;
329 clientCertificate = client;
333 internal bool CallEndPointDelegate (Socket sock, IPEndPoint remote)
335 if (endPointCallback == null)
340 IPEndPoint local = null;
342 local = endPointCallback (this,
345 // This is to differentiate from an
346 // OverflowException, which should propagate.
355 } catch (SocketException) {
356 // This is intentional; the docs say
357 // that if the Bind fails, we keep
358 // going until there is an
359 // OverflowException on the retry