Merge pull request #2092 from kasthack/system-web-stuff-import
[mono.git] / mcs / class / System / System.Net / ServicePoint.cs
index 663816eb9e71e84c03da2dc6f8420b84784d2834..ebac3e9cf1d2760763fd5753cd4c47763de54c71 100644 (file)
@@ -47,12 +47,12 @@ namespace System.Net
                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;
@@ -255,56 +255,35 @@ namespace System.Net
                         */
 
                        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;
                                }
@@ -320,41 +299,34 @@ namespace System.Net
                                 * 
                                 */
 
-                               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;
                                }
 
@@ -368,37 +340,30 @@ namespace System.Net
                        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;
                                        }
                                }
 
@@ -411,7 +376,6 @@ namespace System.Net
                        protocolVersion = version;
                }
 
-#if !TARGET_JVM
                internal EventHandler SendRequest (HttpWebRequest request, string groupName)
                {
                        WebConnection cnc;
@@ -429,17 +393,23 @@ namespace System.Net
                        
                        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;
                }