Merge pull request #5560 from kumpera/wasm-work-p3
[mono.git] / mcs / class / test-helpers / NetworkHelpers.cs
index fcb63961d23eaa7a64e09ba4c7bc835ea05214ac..262b8d33232459be06ddde9a7b9e8f9bfbd7befc 100644 (file)
@@ -1,22 +1,48 @@
 using System;
 using System.Net;
 using System.Net.Sockets;
+using System.Collections.Generic;
 
 namespace MonoTests.Helpers {
 
        public static class NetworkHelpers
        {
+               static Random rndPort = new Random ();
+               static HashSet<int> portsTable = new HashSet<int> ();
+
                public static int FindFreePort ()
                {
-                       TcpListener l = new TcpListener(IPAddress.Loopback, 0);
-                       l.Start();
-                       int port = ((IPEndPoint)l.LocalEndpoint).Port;
-                       l.Stop();
-                       return port;
+                       return LocalEphemeralEndPoint ().Port;
                }
+
                public static IPEndPoint LocalEphemeralEndPoint ()
                {
-                       return new IPEndPoint (IPAddress.Loopback, FindFreePort());
+                       int counter = 0;
+
+                       while (counter < 1000) {
+                               var testingPort = rndPort.Next (10000, 60000);
+
+                               var ep = new IPEndPoint (IPAddress.Loopback, testingPort);
+
+                               lock (portsTable) {
+                                       if (portsTable.Contains (testingPort))
+                                               continue;
+
+                                       ++counter;
+
+                                       try {
+                                               using (var socket = new Socket (ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) {
+                                                       socket.Bind (ep);
+                                                       socket.Close ();
+                                               }
+
+                                               portsTable.Add (testingPort);
+                                               return ep;
+                                       } catch (SocketException) { }
+                               }
+                       }
+
+                       throw new ApplicationException ($"Could not find available local port after {counter} retries");
                }
        }
 }