1 //------------------------------------------------------------------------------
2 // <copyright file="ServicePointManager.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
6 #if MONO_FEATURE_WEB_STACK
9 using System.Collections;
10 using System.Diagnostics.CodeAnalysis;
11 using System.Globalization;
12 using System.Net.Configuration;
13 using System.Net.Security;
14 using System.Runtime.CompilerServices;
15 using System.Security.Authentication;
16 using System.Threading;
19 // The ServicePointManager class hands out ServicePoints (may exist or be created
20 // as needed) and makes sure they are garbage collected when they expire.
21 // The ServicePointManager runs in its own thread so that it never
25 /// <para>Manages the collection of <see cref='System.Net.ServicePoint'/> instances.</para>
28 public partial class ServicePointManager {
32 /// The number of non-persistent connections allowed on a <see cref='System.Net.ServicePoint'/>.
35 public const int DefaultNonPersistentConnectionLimit = 4;
38 /// The default number of persistent connections allowed on a <see cref='System.Net.ServicePoint'/>.
41 public const int DefaultPersistentConnectionLimit = 2;
45 /// The default number of persistent connections when running under ASP+.
48 private const int DefaultAspPersistentConnectionLimit = 10;
51 internal static readonly string SpecialConnectGroupName = "/.NET/NetClasses/HttpWebRequest/CONNECT__Group$$/";
52 internal static readonly TimerThread.Callback s_IdleServicePointTimeoutDelegate = new TimerThread.Callback(IdleServicePointTimeoutCallback);
55 // data - only statics used
59 // s_ServicePointTable - Uri of ServicePoint is the hash key
60 // We provide our own comparer function that knows about Uris
63 //also used as a lock object
64 private static Hashtable s_ServicePointTable = new Hashtable(10);
66 // IIS6 has 120 sec for an idle connection timeout, we should have a little bit less.
67 private static volatile TimerThread.Queue s_ServicePointIdlingQueue = TimerThread.GetOrCreateQueue(100 * 1000);
68 private static int s_MaxServicePoints = 0;
70 private static volatile CertPolicyValidationCallback s_CertPolicyValidationCallback = new CertPolicyValidationCallback();
71 private static volatile ServerCertValidationCallback s_ServerCertValidationCallback = null;
73 private static SecurityProtocolType s_SecurityProtocolType;
75 private static bool s_reusePort;
76 private static bool? s_reusePortSupported = null;
78 private static bool s_disableStrongCrypto;
79 private static bool s_disableSendAuxRecord;
80 private static bool s_disableSystemDefaultTlsVersions;
81 private static SslProtocols s_defaultSslProtocols;
83 #endif // !FEATURE_PAL
85 private static volatile Hashtable s_ConfigTable = null;
86 private static volatile int s_ConnectionLimit = PersistentConnectionLimit;
88 internal static volatile bool s_UseTcpKeepAlive = false;
89 internal static volatile int s_TcpKeepAliveTime;
90 internal static volatile int s_TcpKeepAliveInterval;
93 // InternalConnectionLimit -
94 // set/get Connection Limit on demand, checking config beforehand
97 private static volatile bool s_UserChangedLimit;
98 private static int InternalConnectionLimit {
100 if (s_ConfigTable == null) {
102 s_ConfigTable = ConfigTable;
104 return s_ConnectionLimit;
107 if (s_ConfigTable == null) {
109 s_ConfigTable = ConfigTable;
111 s_UserChangedLimit = true;
112 s_ConnectionLimit = value;
117 // PersistentConnectionLimit -
118 // Determines the correct connection limit based on whether with running with ASP+
119 // The following order is followed generally for figuring what ConnectionLimit size to use
120 // 1. If ServicePoint.ConnectionLimit is set, then take that value
121 // 2. If ServicePoint has a specific config setting, then take that value
122 // 3. If ServicePoint.DefaultConnectionLimit is set, then take that value
123 // 4. If ServicePoint is localhost, then set to infinite (TO Should we change this value?)
124 // 5. If ServicePointManager has a default config connection limit setting, then take that value
125 // 6. If ServicePoint is running under ASP+, then set value to 10, else set it to 2
127 private static int PersistentConnectionLimit {
130 if (ComNetOS.IsAspNetServer) {
131 return DefaultAspPersistentConnectionLimit;
135 return DefaultPersistentConnectionLimit;
142 // InternalServicePointCount -
143 // Gets the active number of ServicePoints being used
145 internal static int InternalServicePointCount {
147 return s_ServicePointTable.Count;
152 [System.Diagnostics.Conditional("DEBUG")]
153 internal static void DebugMembers(int requestHash) {
155 foreach (WeakReference servicePointReference in s_ServicePointTable) {
156 ServicePoint servicePoint;
157 if (servicePointReference != null && servicePointReference.IsAlive) {
158 servicePoint = (ServicePoint)servicePointReference.Target;
163 if (servicePoint!=null) {
164 servicePoint.DebugMembers(requestHash);
168 catch (Exception e) {
169 if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
177 // read ConfigTable from Config, or create
178 // a default on failure
181 private static Hashtable ConfigTable {
183 if (s_ConfigTable == null) {
184 lock(s_ServicePointTable) {
185 if (s_ConfigTable == null) {
186 ConnectionManagementSectionInternal configSection
187 = ConnectionManagementSectionInternal.GetSection();
188 Hashtable configTable = null;
189 if (configSection != null)
191 configTable = configSection.ConnectionManagement;
194 if (configTable == null) {
195 configTable = new Hashtable();
198 // we piggy back loading the ConnectionLimit here
199 if (configTable.ContainsKey("*") ) {
200 int connectionLimit = (int) configTable["*"];
201 if ( connectionLimit < 1 ) {
202 connectionLimit = PersistentConnectionLimit;
204 s_ConnectionLimit = connectionLimit;
206 s_ConfigTable = configTable;
210 return s_ConfigTable;
215 internal static TimerThread.Callback IdleServicePointTimeoutDelegate
219 return s_IdleServicePointTimeoutDelegate;
223 private static void IdleServicePointTimeoutCallback(TimerThread.Timer timer, int timeNoticed, object context)
225 ServicePoint servicePoint = (ServicePoint) context;
227 if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_closed_idle,
228 "ServicePoint", servicePoint.GetHashCode()));
230 lock (s_ServicePointTable)
232 s_ServicePointTable.Remove(servicePoint.LookupString);
235 servicePoint.ReleaseAllConnectionGroups();
243 private ServicePointManager() {
247 [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety")]
248 public static SecurityProtocolType SecurityProtocol {
250 EnsureConfigurationLoaded();
251 return s_SecurityProtocolType;
254 EnsureConfigurationLoaded();
255 ValidateSecurityProtocol(value);
256 s_SecurityProtocolType = value;
260 private static void ValidateSecurityProtocol(SecurityProtocolType value)
262 // Do not allow Ssl2 (and others) as explicit SSL version request.
263 SecurityProtocolType allowed = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls
264 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
266 Debug.Assert((int)SecurityProtocolType.SystemDefault == (int)SslProtocols.None);
267 Debug.Assert((int)SecurityProtocolType.Ssl3 == (int)SslProtocols.Ssl3);
268 Debug.Assert((int)SecurityProtocolType.Tls == (int)SslProtocols.Tls);
269 Debug.Assert((int)SecurityProtocolType.Tls11 == (int)SslProtocols.Tls11);
270 Debug.Assert((int)SecurityProtocolType.Tls12 == (int)SslProtocols.Tls12);
272 if ((value & ~allowed) != 0)
274 throw new NotSupportedException(SR.GetString(SR.net_securityprotocolnotsupported));
277 #endif // !FEATURE_PAL
279 internal static bool DisableStrongCrypto
283 EnsureConfigurationLoaded();
284 return s_disableStrongCrypto;
288 internal static bool DisableSystemDefaultTlsVersions
292 EnsureConfigurationLoaded();
293 return s_disableSystemDefaultTlsVersions;
297 internal static bool DisableSendAuxRecord
301 EnsureConfigurationLoaded();
302 return s_disableSendAuxRecord;
306 internal static SslProtocols DefaultSslProtocols
310 EnsureConfigurationLoaded();
311 return s_defaultSslProtocols;
320 /// <para>Gets or sets the maximum number of <see cref='System.Net.ServicePoint'/> instances that should be maintained at any
323 [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety")]
324 public static int MaxServicePoints {
326 return s_MaxServicePoints;
329 ExceptionHelper.WebPermissionUnrestricted.Demand();
330 if (!ValidationHelper.ValidateRange(value, 0, Int32.MaxValue)) {
331 throw new ArgumentOutOfRangeException("value");
333 s_MaxServicePoints = value;
338 /// <para>[To be supplied.]</para>
340 public static int DefaultConnectionLimit {
342 return InternalConnectionLimit;
345 ExceptionHelper.WebPermissionUnrestricted.Demand();
347 InternalConnectionLimit = value;
351 throw new ArgumentOutOfRangeException("value", SR.GetString(SR.net_toosmall));
359 /// <para>Gets or sets the maximum idle time in seconds of a <see cref='System.Net.ServicePoint'/>.</para>
361 public static int MaxServicePointIdleTime {
363 return s_ServicePointIdlingQueue.Duration;
366 ExceptionHelper.WebPermissionUnrestricted.Demand();
367 if ( !ValidationHelper.ValidateRange(value, Timeout.Infinite, Int32.MaxValue)) {
368 throw new ArgumentOutOfRangeException("value");
370 if (s_ServicePointIdlingQueue.Duration != value)
372 s_ServicePointIdlingQueue = TimerThread.GetOrCreateQueue(value);
379 /// Gets or sets indication whether use of the Nagling algorithm is desired.
380 /// Changing this value does not affect existing <see cref='System.Net.ServicePoint'/> instances but only to new ones that are created from that moment on.
383 public static bool UseNagleAlgorithm {
385 return SettingsSectionInternal.Section.UseNagleAlgorithm;
388 SettingsSectionInternal.Section.UseNagleAlgorithm = value;
394 /// Gets or sets indication whether 100-continue behaviour is desired.
395 /// Changing this value does not affect existing <see cref='System.Net.ServicePoint'/> instances but only to new ones that are created from that moment on.
398 public static bool Expect100Continue {
400 return SettingsSectionInternal.Section.Expect100Continue;
403 SettingsSectionInternal.Section.Expect100Continue = value;
409 /// Enables the use of DNS round robin access, meaning a different IP
410 /// address may be used on each connection, when more than one IP is availble
413 public static bool EnableDnsRoundRobin {
415 return SettingsSectionInternal.Section.EnableDnsRoundRobin;
418 SettingsSectionInternal.Section.EnableDnsRoundRobin = value;
424 /// Causes us to go back and reresolve addresses through DNS, even when
425 /// there were no recorded failures. -1 is infinite. Time should be in ms
428 public static int DnsRefreshTimeout {
430 return SettingsSectionInternal.Section.DnsRefreshTimeout;
434 SettingsSectionInternal.Section.DnsRefreshTimeout = -1;
437 SettingsSectionInternal.Section.DnsRefreshTimeout = value;
445 /// Defines the s_Policy for how to deal with server certificates.
450 [Obsolete("CertificatePolicy is obsoleted for this type, please use ServerCertificateValidationCallback instead. http://go.microsoft.com/fwlink/?linkid=14202")]
451 public static ICertificatePolicy CertificatePolicy {
453 return GetLegacyCertificatePolicy();
456 //Prevent for an applet to override default Certificate Policy
457 ExceptionHelper.UnmanagedPermission.Demand();
458 s_CertPolicyValidationCallback = new CertPolicyValidationCallback(value);
462 internal static ICertificatePolicy GetLegacyCertificatePolicy(){
463 if (s_CertPolicyValidationCallback == null)
466 return s_CertPolicyValidationCallback.CertificatePolicy;
469 internal static CertPolicyValidationCallback CertPolicyValidationCallback {
471 return s_CertPolicyValidationCallback;
476 public static RemoteCertificateValidationCallback ServerCertificateValidationCallback {
478 if (s_ServerCertValidationCallback == null)
481 return s_ServerCertValidationCallback.ValidationCallback;
484 // Prevent an applet from overriding the default Certificate Policy
485 ExceptionHelper.InfrastructurePermission.Demand();
488 s_ServerCertValidationCallback = null;
492 s_ServerCertValidationCallback = new ServerCertValidationCallback(value);
497 internal static ServerCertValidationCallback ServerCertValidationCallback {
499 return s_ServerCertValidationCallback;
503 public static bool ReusePort {
512 internal static bool? ReusePortSupported
516 return s_reusePortSupported;
520 s_reusePortSupported = value;
523 #endif // !FEATURE_PAL
525 public static bool CheckCertificateRevocationList {
527 return SettingsSectionInternal.Section.CheckCertificateRevocationList;
530 //Prevent an applet to override default certificate checking
531 ExceptionHelper.UnmanagedPermission.Demand();
532 SettingsSectionInternal.Section.CheckCertificateRevocationList = value;
536 public static EncryptionPolicy EncryptionPolicy {
538 return SettingsSectionInternal.Section.EncryptionPolicy;
542 internal static bool CheckCertificateName {
544 return SettingsSectionInternal.Section.CheckCertificateName;
554 // MakeQueryString - Just a short macro to handle creating the query
555 // string that we search for host ports in the host list
557 internal static string MakeQueryString(Uri address) {
558 if (address.IsDefaultPort)
559 return address.Scheme + "://" + address.DnsSafeHost;
561 return address.Scheme + "://" + address.DnsSafeHost + ":" + address.Port.ToString();
564 internal static string MakeQueryString(Uri address1, bool isProxy) {
566 return MakeQueryString(address1) + "://proxy";
569 return MakeQueryString(address1);
574 // FindServicePoint - Query using an Uri string for a given ServerPoint Object
578 /// <para>Finds an existing <see cref='System.Net.ServicePoint'/> or creates a new <see cref='System.Net.ServicePoint'/> to manage communications to the
579 /// specified Uniform Resource Identifier.</para>
581 public static ServicePoint FindServicePoint(Uri address) {
582 return FindServicePoint(address, null);
587 /// <para>Finds an existing <see cref='System.Net.ServicePoint'/> or creates a new <see cref='System.Net.ServicePoint'/> to manage communications to the
588 /// specified Uniform Resource Identifier.</para>
590 public static ServicePoint FindServicePoint(string uriString, IWebProxy proxy) {
591 Uri uri = new Uri(uriString);
592 return FindServicePoint(uri, proxy);
597 // FindServicePoint - Query using an Uri for a given server point
601 /// <para>Findes an existing <see cref='System.Net.ServicePoint'/> or creates a new <see cref='System.Net.ServicePoint'/> to manage communications to the specified <see cref='System.Uri'/>
604 public static ServicePoint FindServicePoint(Uri address, IWebProxy proxy) {
606 HttpAbortDelegate abortDelegate = null;
608 return FindServicePoint(address, proxy, out chain, ref abortDelegate, ref abortState);
611 // If abortState becomes non-zero, the attempt to find a service point has been aborted.
612 internal static ServicePoint FindServicePoint(Uri address, IWebProxy proxy, out ProxyChain chain, ref HttpAbortDelegate abortDelegate, ref int abortState)
615 throw new ArgumentNullException("address");
617 GlobalLog.Enter("ServicePointManager::FindServicePoint() address:" + address.ToString());
619 bool isProxyServicePoint = false;
623 // find proxy info, and then switch on proxy
625 Uri proxyAddress = null;
626 if (proxy!=null && !address.IsLoopback) {
627 IAutoWebProxy autoProxy = proxy as IAutoWebProxy;
628 if (autoProxy != null)
630 chain = autoProxy.GetProxies(address);
632 // Set up our ability to abort this MoveNext call. Note that the current implementations of ProxyChain will only
633 // take time on the first call, so this is the only place we do this. If a new ProxyChain takes time in later
634 // calls, this logic should be copied to other places MoveNext is called.
635 GlobalLog.Assert(abortDelegate == null, "ServicePointManager::FindServicePoint()|AbortDelegate already set.");
636 abortDelegate = chain.HttpAbortDelegate;
639 Thread.MemoryBarrier();
642 Exception exception = new WebException(NetRes.GetWebStatusString(WebExceptionStatus.RequestCanceled), WebExceptionStatus.RequestCanceled);
643 GlobalLog.LeaveException("ServicePointManager::FindServicePoint() Request aborted before proxy lookup.", exception);
647 if (!chain.Enumerator.MoveNext())
649 GlobalLog.Assert("ServicePointManager::FindServicePoint()|GetProxies() returned zero proxies.");
651 Exception exception = new WebException(NetRes.GetWebStatusString(WebExceptionStatus.RequestProhibitedByProxy), WebExceptionStatus.RequestProhibitedByProxy);
652 GlobalLog.LeaveException("ServicePointManager::FindServicePoint() Proxy prevented request.", exception);
656 proxyAddress = chain.Enumerator.Current;
660 abortDelegate = null;
663 else if (!proxy.IsBypassed(address))
667 proxyAddress = proxy.GetProxy(address);
671 if (proxyAddress!=null) {
672 address = proxyAddress;
673 isProxyServicePoint = true;
677 ServicePoint servicePoint = FindServicePointHelper(address, isProxyServicePoint);
678 GlobalLog.Leave("ServicePointManager::FindServicePoint() servicePoint#" + ValidationHelper.HashString(servicePoint));
682 // Returns null if we get to the end of the chain.
683 internal static ServicePoint FindServicePoint(ProxyChain chain)
685 GlobalLog.Print("ServicePointManager::FindServicePoint() Calling chained version.");
686 if (!chain.Enumerator.MoveNext())
691 Uri proxyAddress = chain.Enumerator.Current;
692 return FindServicePointHelper(proxyAddress == null ? chain.Destination : proxyAddress, proxyAddress != null);
695 private static ServicePoint FindServicePointHelper(Uri address, bool isProxyServicePoint)
697 GlobalLog.Enter("ServicePointManager::FindServicePointHelper() address:" + address.ToString());
699 if (isProxyServicePoint)
701 if (address.Scheme != Uri.UriSchemeHttp)
707 Exception exception = new NotSupportedException(SR.GetString(SR.net_proxyschemenotsupported, address.Scheme));
708 GlobalLog.LeaveException("ServicePointManager::FindServicePointHelper() proxy has unsupported scheme:" + address.Scheme.ToString(), exception);
714 // Search for the correct proxy host,
715 // then match its acutal host by using ConnectionGroups
716 // which are located on the actual ServicePoint.
718 string tempEntry = MakeQueryString(address, isProxyServicePoint);
720 // lookup service point in the table
721 ServicePoint servicePoint = null;
722 GlobalLog.Print("ServicePointManager::FindServicePointHelper() locking and looking up tempEntry:[" + tempEntry.ToString() + "]");
723 lock (s_ServicePointTable) {
724 // once we grab the lock, check if it wasn't already added
725 WeakReference servicePointReference = s_ServicePointTable[tempEntry] as WeakReference;
726 GlobalLog.Print("ServicePointManager::FindServicePointHelper() lookup returned WeakReference#" + ValidationHelper.HashString(servicePointReference));
727 if ( servicePointReference != null ) {
728 servicePoint = (ServicePoint)servicePointReference.Target;
729 GlobalLog.Print("ServicePointManager::FindServicePointHelper() successful lookup returned ServicePoint#" + ValidationHelper.HashString(servicePoint));
731 if (servicePoint==null) {
732 // lookup failure or timeout, we need to create a new ServicePoint
733 if (s_MaxServicePoints<=0 || s_ServicePointTable.Count<s_MaxServicePoints) {
734 // Determine Connection Limit
735 int connectionLimit = InternalConnectionLimit;
736 string schemeHostPort = MakeQueryString(address);
737 bool userDefined = s_UserChangedLimit;
738 if (ConfigTable.ContainsKey(schemeHostPort) ) {
739 connectionLimit = (int) ConfigTable[schemeHostPort];
742 servicePoint = new ServicePoint(address, s_ServicePointIdlingQueue, connectionLimit, tempEntry, userDefined, isProxyServicePoint);
743 GlobalLog.Print("ServicePointManager::FindServicePointHelper() created ServicePoint#" + ValidationHelper.HashString(servicePoint));
744 servicePointReference = new WeakReference(servicePoint);
745 s_ServicePointTable[tempEntry] = servicePointReference;
746 GlobalLog.Print("ServicePointManager::FindServicePointHelper() adding entry WeakReference#" + ValidationHelper.HashString(servicePointReference) + " key:[" + tempEntry + "]");
749 Exception exception = new InvalidOperationException(SR.GetString(SR.net_maxsrvpoints));
750 GlobalLog.LeaveException("ServicePointManager::FindServicePointHelper() reached the limit count:" + s_ServicePointTable.Count.ToString() + " limit:" + s_MaxServicePoints.ToString(), exception);
756 GlobalLog.Leave("ServicePointManager::FindServicePointHelper() servicePoint#" + ValidationHelper.HashString(servicePoint));
761 // FindServicePoint - Query using an Uri for a given server point
765 /// <para>Findes an existing <see cref='System.Net.ServicePoint'/> or creates a new <see cref='System.Net.ServicePoint'/> to manage communications to the specified <see cref='System.Uri'/>
768 internal static ServicePoint FindServicePoint(string host, int port) {
770 throw new ArgumentNullException("address");
772 GlobalLog.Enter("ServicePointManager::FindServicePoint() host:" + host.ToString());
774 string tempEntry = null;
775 bool isProxyServicePoint = false;
779 // Search for the correct proxy host,
780 // then match its acutal host by using ConnectionGroups
781 // which are located on the actual ServicePoint.
783 tempEntry = "ByHost:"+host+":"+port.ToString(CultureInfo.InvariantCulture);
784 // lookup service point in the table
785 ServicePoint servicePoint = null;
786 GlobalLog.Print("ServicePointManager::FindServicePoint() locking and looking up tempEntry:[" + tempEntry.ToString() + "]");
787 lock (s_ServicePointTable) {
788 // once we grab the lock, check if it wasn't already added
789 WeakReference servicePointReference = s_ServicePointTable[tempEntry] as WeakReference;
790 GlobalLog.Print("ServicePointManager::FindServicePoint() lookup returned WeakReference#" + ValidationHelper.HashString(servicePointReference));
791 if ( servicePointReference != null ) {
792 servicePoint = (ServicePoint)servicePointReference.Target;
793 GlobalLog.Print("ServicePointManager::FindServicePoint() successfull lookup returned ServicePoint#" + ValidationHelper.HashString(servicePoint));
795 if (servicePoint==null) {
796 // lookup failure or timeout, we need to create a new ServicePoint
797 if (s_MaxServicePoints<=0 || s_ServicePointTable.Count<s_MaxServicePoints) {
798 // Determine Connection Limit
799 int connectionLimit = InternalConnectionLimit;
800 bool userDefined = s_UserChangedLimit;
801 string schemeHostPort =host+":"+port.ToString(CultureInfo.InvariantCulture);
803 if (ConfigTable.ContainsKey(schemeHostPort) ) {
804 connectionLimit = (int) ConfigTable[schemeHostPort];
807 servicePoint = new ServicePoint(host, port, s_ServicePointIdlingQueue, connectionLimit, tempEntry, userDefined, isProxyServicePoint);
808 GlobalLog.Print("ServicePointManager::FindServicePoint() created ServicePoint#" + ValidationHelper.HashString(servicePoint));
809 servicePointReference = new WeakReference(servicePoint);
810 s_ServicePointTable[tempEntry] = servicePointReference;
811 GlobalLog.Print("ServicePointManager::FindServicePoint() adding entry WeakReference#" + ValidationHelper.HashString(servicePointReference) + " key:[" + tempEntry + "]");
814 Exception exception = new InvalidOperationException(SR.GetString(SR.net_maxsrvpoints));
815 GlobalLog.LeaveException("ServicePointManager::FindServicePoint() reached the limit count:" + s_ServicePointTable.Count.ToString() + " limit:" + s_MaxServicePoints.ToString(), exception);
821 GlobalLog.Leave("ServicePointManager::FindServicePoint() servicePoint#" + ValidationHelper.HashString(servicePoint));
825 [FriendAccessAllowed]
826 internal static void CloseConnectionGroups(string connectionGroupName) {
827 // This method iterates through all service points and closes connection groups with the provided name.
828 ServicePoint servicePoint = null;
829 lock (s_ServicePointTable) {
830 foreach (DictionaryEntry item in s_ServicePointTable) {
831 WeakReference servicePointReference = item.Value as WeakReference;
832 if (servicePointReference != null) {
833 servicePoint = (ServicePoint)servicePointReference.Target;
834 if (servicePoint != null) {
835 // We found a service point. Ask the service point to close all internal connection groups
836 // with name 'connectionGroupName'.
837 servicePoint.CloseConnectionGroupInternal(connectionGroupName);
847 // Enable/Disable the use of TCP keepalive option on ServicePoint
848 // connections. This method does not affect existing ServicePoints.
849 // When a ServicePoint is constructed it will inherit the current
854 // enabled - if true enables the use of the TCP keepalive option
855 // for ServicePoint connections.
857 // keepAliveTime - specifies the timeout, in milliseconds, with no
858 // activity until the first keep-alive packet is sent. Ignored if
859 // enabled parameter is false.
861 // keepAliveInterval - specifies the interval, in milliseconds, between
862 // when successive keep-alive packets are sent if no acknowledgement is
863 // received. Ignored if enabled parameter is false.
865 public static void SetTcpKeepAlive(
868 int keepAliveInterval) {
871 "ServicePointManager::SetTcpKeepAlive()" +
872 " enabled: " + enabled.ToString() +
873 " keepAliveTime: " + keepAliveTime.ToString() +
874 " keepAliveInterval: " + keepAliveInterval.ToString()
877 s_UseTcpKeepAlive = true;
878 if (keepAliveTime <= 0) {
879 throw new ArgumentOutOfRangeException("keepAliveTime");
881 if (keepAliveInterval <= 0) {
882 throw new ArgumentOutOfRangeException("keepAliveInterval");
884 s_TcpKeepAliveTime = keepAliveTime;
885 s_TcpKeepAliveInterval = keepAliveInterval;
887 s_UseTcpKeepAlive = false;
888 s_TcpKeepAliveTime = 0;
889 s_TcpKeepAliveInterval =0;
891 GlobalLog.Leave("ServicePointManager::SetTcpKeepAlive()");