using System.Linq;
using System.Collections;
using System.Threading;
+using System.Reflection;
using System.Text.RegularExpressions;
using System.Net;
using System.Net.Sockets;
s.Close ();
}
- static bool supportsTcpReuse = false;
- static bool supportsTcpReuseSet = false;
-
- static bool SupportsTcpReuse ()
+ static bool? supportsPortReuse;
+ static bool SupportsPortReuse ()
{
- if (supportsTcpReuseSet)
- return supportsTcpReuse;
-
- if (Path.DirectorySeparatorChar == '/') {
- /*
- * On UNIX OS
- * Multiple threads listening to the same address and port are not possible
- * before linux 3.9 kernel, where the socket option SO_REUSEPORT was introduced.
- */
- Regex reg = new Regex(@"^#define\s*SO_REUSEPORT");
- foreach (string directory in Directory.GetDirectories ("/usr/include")) {
- var f = Directory.GetFiles (directory, "socket.h").SingleOrDefault ();
- if (f != null && File.ReadLines (f).Any (l => reg.Match (l).Success)) {
- supportsTcpReuse = true;
- break;
- }
- }
- } else {
- supportsTcpReuse = true;
- }
-
- supportsTcpReuseSet = true;
+ if (supportsPortReuse.HasValue)
+ return supportsPortReuse.Value;
- return supportsTcpReuse;
+ supportsPortReuse = (bool) typeof (Socket).GetMethod ("SupportsPortReuse",
+ BindingFlags.Static | BindingFlags.NonPublic)
+ .Invoke (null, new object [] {});
+ return supportsPortReuse.Value;
}
// Test case for bug #31557
ex = e;
}
- Assert.AreEqual (SupportsTcpReuse (), ex == null);
+ Assert.AreEqual (SupportsPortReuse (), ex == null);
}
}
ICALL(SOCK_18, "SetSocketOption_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object,byte[],int,int&)", ves_icall_System_Net_Sockets_Socket_SetSocketOption_internal)
ICALL(SOCK_19, "Shutdown_internal(intptr,System.Net.Sockets.SocketShutdown,int&)", ves_icall_System_Net_Sockets_Socket_Shutdown_internal)
ICALL(SOCK_20, "Socket_internal(System.Net.Sockets.AddressFamily,System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType,int&)", ves_icall_System_Net_Sockets_Socket_Socket_internal)
+ICALL(SOCK_20a, "SupportsPortReuse", ves_icall_System_Net_Sockets_Socket_SupportPortReuse)
ICALL(SOCK_21a, "cancel_blocking_socket_operation", icall_cancel_blocking_socket_operation)
ICALL_TYPE(SOCKEX, "System.Net.Sockets.SocketException", SOCKEX_1)
extern void ves_icall_System_Net_Sockets_Socket_Disconnect_internal(SOCKET sock, MonoBoolean reuse, gint32 *error);
extern gboolean ves_icall_System_Net_Sockets_Socket_SendFile_internal (SOCKET sock, MonoString *filename, MonoArray *pre_buffer, MonoArray *post_buffer, gint flags);
void icall_cancel_blocking_socket_operation (MonoThread *thread);
+extern gboolean ves_icall_System_Net_Sockets_Socket_SupportPortReuse (void);
extern void mono_network_init(void);
extern void mono_network_cleanup(void);