int maxIdleTime;
int currentConnections;
DateTime idleSince;
+ DateTime lastDnsResolve;
Version protocolVersion;
X509Certificate certificate;
X509Certificate clientCertificate;
IPHostEntry host;
bool usesProxy;
- WebConnectionGroup firstGroup;
Dictionary<string,WebConnectionGroup> groups;
bool sendContinue = true;
bool useConnect;
*/
WebConnectionGroup group;
- if (firstGroup != null && name == firstGroup.Name)
- return firstGroup;
if (groups != null && groups.TryGetValue (name, out group))
return group;
group = new WebConnectionGroup (this, name);
group.ConnectionClosed += (s, e) => currentConnections--;
- if (firstGroup == null)
- firstGroup = group;
- else {
- if (groups == null)
- groups = new Dictionary<string, WebConnectionGroup> ();
- groups.Add (name, group);
- }
+ if (groups == null)
+ groups = new Dictionary<string, WebConnectionGroup> ();
+ groups.Add (name, group);
return group;
}
void RemoveConnectionGroup (WebConnectionGroup group)
{
- if (groups == null || groups.Count == 0) {
- // No more connection groups left.
- if (group != firstGroup)
- throw new InvalidOperationException ();
- else
- firstGroup = null;
- return;
- }
+ if (groups == null || groups.Count == 0)
+ throw new InvalidOperationException ();
- if (group == firstGroup) {
- // Steal one entry from the dictionary.
- var en = groups.GetEnumerator ();
- en.MoveNext ();
- firstGroup = en.Current.Value;
- groups.Remove (en.Current.Key);
- } else {
- groups.Remove (group.Name);
- }
+ groups.Remove (group.Name);
}
- internal bool CheckAvailableForRecycling (out DateTime outIdleSince)
+ bool CheckAvailableForRecycling (out DateTime outIdleSince)
{
outIdleSince = DateTime.MinValue;
TimeSpan idleTimeSpan;
- WebConnectionGroup singleGroup, singleRemove = null;
List<WebConnectionGroup> groupList = null, removeList = null;
lock (this) {
- if (firstGroup == null) {
+ if (groups == null || groups.Count == 0) {
idleSince = DateTime.MinValue;
return true;
}
*
*/
- singleGroup = firstGroup;
- if (groups != null)
- groupList = new List<WebConnectionGroup> (groups.Values);
+ groupList = new List<WebConnectionGroup> (groups.Values);
}
- if (singleGroup.TryRecycle (idleTimeSpan, ref outIdleSince))
- singleRemove = singleGroup;
-
- if (groupList != null) {
- foreach (var group in groupList) {
- if (!group.TryRecycle (idleTimeSpan, ref outIdleSince))
- continue;
- if (removeList == null)
- removeList = new List<WebConnectionGroup> ();
- removeList.Add (group);
- }
+ foreach (var group in groupList) {
+ if (!group.TryRecycle (idleTimeSpan, ref outIdleSince))
+ continue;
+ if (removeList == null)
+ removeList = new List<WebConnectionGroup> ();
+ removeList.Add (group);
}
lock (this) {
idleSince = outIdleSince;
- if (singleRemove != null)
- RemoveConnectionGroup (singleRemove);
-
- if (removeList != null) {
+ if (removeList != null && groups != null) {
foreach (var group in removeList)
- RemoveConnectionGroup (group);
+ if (groups.ContainsKey (group.Name))
+ RemoveConnectionGroup (group);
}
if (groups != null && groups.Count == 0)
groups = null;
- if (firstGroup == null) {
- idleTimer.Dispose ();
- idleTimer = null;
+ if (groups == null) {
+ if (idleTimer != null) {
+ idleTimer.Dispose ();
+ idleTimer = null;
+ }
return true;
}
CheckAvailableForRecycling (out dummy);
}
+ private bool HasTimedOut
+ {
+ get {
+ int timeout = ServicePointManager.DnsRefreshTimeout;
+ return timeout != Timeout.Infinite &&
+ (lastDnsResolve + TimeSpan.FromMilliseconds (timeout)) < DateTime.UtcNow;
+ }
+ }
+
internal IPHostEntry HostEntry
{
get {
lock (hostE) {
- if (host != null)
- return host;
-
string uriHost = uri.Host;
- // There is no need to do DNS resolution on literal IP addresses
- if (uri.HostNameType == UriHostNameType.IPv6 ||
- uri.HostNameType == UriHostNameType.IPv4) {
+ if (host == null || HasTimedOut) {
+ lastDnsResolve = DateTime.UtcNow;
- if (uri.HostNameType == UriHostNameType.IPv6) {
- // Remove square brackets
- uriHost = uriHost.Substring(1,uriHost.Length-2);
+ try {
+ host = Dns.GetHostEntry (uriHost);
+ }
+ catch (Exception) {
+ return null;
}
-
- // Creates IPHostEntry
- host = new IPHostEntry();
- host.AddressList = new IPAddress[] { IPAddress.Parse(uriHost) };
-
- return host;
- }
-
- // Try DNS resolution on host names
- try {
- host = Dns.GetHostByName (uriHost);
- }
- catch {
- return null;
}
}
protocolVersion = version;
}
-#if !TARGET_JVM
internal EventHandler SendRequest (HttpWebRequest request, string groupName)
{
WebConnection cnc;
return cnc.SendRequest (request);
}
-#endif
public bool CloseConnectionGroup (string connectionGroupName)
{
+ WebConnectionGroup cncGroup = null;
+
lock (this) {
- WebConnectionGroup cncGroup = GetConnectionGroup (connectionGroupName);
+ cncGroup = GetConnectionGroup (connectionGroupName);
if (cncGroup != null) {
- cncGroup.Close ();
- return true;
+ RemoveConnectionGroup (cncGroup);
}
}
+ // WebConnectionGroup.Close() must *not* be called inside the lock
+ if (cncGroup != null) {
+ cncGroup.Close ();
+ return true;
+ }
+
return false;
}