Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ServicePointManager.cs « System.Net « System « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2dc6831761dfd4691aa81cdc313214533f661cae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//
// System.Net.ServicePointManager
//
// Author:
//   Lawrence Pit (loz@cable.a2000.nl)
//

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Security.Cryptography.X509Certificates;

//
// 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 class ServicePointManager
	{
		private static HybridDictionary servicePoints = new HybridDictionary ();
		
		// Static properties
		
		private static ICertificatePolicy policy = null;
		private static int defaultConnectionLimit = DefaultPersistentConnectionLimit;
		private static int maxServicePointIdleTime = 900000; // 15 minutes
		private static int maxServicePoints = 0;
		
		// Fields
		
		public const int DefaultNonPersistentConnectionLimit = 4;
		public const int DefaultPersistentConnectionLimit = 2;
		
		// Constructors
		private ServicePointManager ()
		{
		}		
		
		// Properties
		
		public static ICertificatePolicy CertificatePolicy {
			get { return policy; }
			set { policy = value; }
		}
		
		public static int DefaultConnectionLimit {
			get { return defaultConnectionLimit; }
			set { 
				if (value < 0)
					throw new ArgumentOutOfRangeException ("value");
				defaultConnectionLimit = value; 
			}
		}
		
		public static int MaxServicePointIdleTime {
			get { 
				return maxServicePointIdleTime;
			}
			set { 
				if (value < -2 || value > Int32.MaxValue)
					throw new ArgumentOutOfRangeException ("value");
				maxServicePointIdleTime = value;
			}
		}
		
		public static int MaxServicePoints {
			get { 
				return maxServicePoints; 
			}
			set {  
				if (value < 0)
					throw new ArgumentException ("value");				
				maxServicePoints = value;
				RecycleServicePoints ();
			}
		}
		
		// Methods
		
		public static ServicePoint FindServicePoint (Uri address) 
		{
			return FindServicePoint (address, GlobalProxySelection.Select);
		}
		
		public static ServicePoint FindServicePoint (string uriString, IWebProxy proxy)
		{
			return FindServicePoint (new Uri(uriString), proxy);
		}
		
		public static ServicePoint FindServicePoint (Uri address, IWebProxy proxy)
		{
			RecycleServicePoints ();
			
			if (address == null)
				throw new ArgumentNullException ("address");

			if (proxy != null && !proxy.IsBypassed(address)) {
				address = proxy.GetProxy (address);				
			} 

			address = new Uri (address.Scheme + "://" + address.Authority);
			
			ServicePoint sp = null;
			lock (servicePoints) {
				sp = (ServicePoint) servicePoints [address];
				if (sp != null)
					return sp;
				if (maxServicePoints > 0 && servicePoints.Count >= maxServicePoints)
					throw new InvalidOperationException ("maximum number of service points reached");
				sp = new ServicePoint (address, defaultConnectionLimit, maxServicePointIdleTime);
				servicePoints.Add (address, sp);
			}
			
			return sp;
		}
		
		// Internal Methods

		internal static void RecycleServicePoints ()
		{
			ArrayList toRemove = new ArrayList ();
			lock (servicePoints) {
				IDictionaryEnumerator e = servicePoints.GetEnumerator ();
				while (e.MoveNext ()) {
					ServicePoint sp = (ServicePoint) e.Value;
					if (sp.AvailableForRecycling) {
						toRemove.Add (e.Key);
					}
				}
				
				for (int i = 0; i < toRemove.Count; i++) 
					servicePoints.Remove (toRemove [i]);

				if (maxServicePoints == 0 || servicePoints.Count <= maxServicePoints)
					return;

				// get rid of the ones with the longest idle time
				SortedList list = new SortedList (servicePoints.Count);
				e = servicePoints.GetEnumerator ();
				while (e.MoveNext ()) {
					ServicePoint sp = (ServicePoint) e.Value;
					if (sp.CurrentConnections == 0) {
						while (list.ContainsKey (sp.IdleSince))
							sp.IdleSince.AddMilliseconds (1);
						list.Add (sp.IdleSince, sp.Address);
					}
				}
				
				for (int i = 0; i < list.Count && servicePoints.Count > maxServicePoints; i++)
					servicePoints.Remove (list.GetByIndex (i));
			}
		}
	}
}