mirror of https://github.com/icedream/npsharp.git
NPServer now in 2 flavours, mono-compatible (2 sockets for IPv4 and IPv6) and mono-incompatible (Win32-proprietary fallback socket)
parent
3c2ed60f5e
commit
cce59f8124
|
@ -21,7 +21,12 @@ namespace NPSharp.NP
|
||||||
private readonly List<NPServerClient> _clients;
|
private readonly List<NPServerClient> _clients;
|
||||||
private readonly ILog _log;
|
private readonly ILog _log;
|
||||||
private readonly ushort _port;
|
private readonly ushort _port;
|
||||||
|
#if MONO_INCOMPATIBLE
|
||||||
private readonly Socket _socket;
|
private readonly Socket _socket;
|
||||||
|
#else
|
||||||
|
private readonly Socket _socket4;
|
||||||
|
private readonly Socket _socket6;
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new NP server.
|
/// Constructs a new NP server.
|
||||||
|
@ -31,13 +36,19 @@ namespace NPSharp.NP
|
||||||
_log = LogManager.GetLogger("NPServer");
|
_log = LogManager.GetLogger("NPServer");
|
||||||
_clients = new List<NPServerClient>();
|
_clients = new List<NPServerClient>();
|
||||||
|
|
||||||
|
#if MONO_INCOMPATIBLE
|
||||||
// Mono can't compile this since the constructor is proprietary to Windows' .NET library
|
// Mono can't compile this since the constructor is proprietary to Windows' .NET library
|
||||||
//_socket = new Socket(SocketType.Stream, ProtocolType.IP);
|
_socket = new Socket(SocketType.Stream, ProtocolType.IP);
|
||||||
|
|
||||||
// Instead we will specifically disable the socket's property to ignore IPv4
|
|
||||||
_socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
|
|
||||||
_socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
|
|
||||||
|
|
||||||
|
// Mono can't compile this either since the IPv6Only socket option is completely missing.
|
||||||
|
//_socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
//_socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
|
||||||
|
#else
|
||||||
|
// So as much as this hurts me, I have to go with TWO sockets.
|
||||||
|
// Guys, this is why I hate network programming sometimes. SOMETIMES.
|
||||||
|
_socket4 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
_socket6 = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
#endif
|
||||||
_port = port;
|
_port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +85,13 @@ namespace NPSharp.NP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
if (_socket.IsBound)
|
if (
|
||||||
|
#if MONO_INCOMPATIBLE
|
||||||
|
_socket.IsBound
|
||||||
|
#else
|
||||||
|
_socket4.IsBound || _socket6.IsBound
|
||||||
|
#endif
|
||||||
|
)
|
||||||
throw new InvalidOperationException("This server is already running");
|
throw new InvalidOperationException("This server is already running");
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -89,17 +106,36 @@ namespace NPSharp.NP
|
||||||
throw new SocketException(10013 /* Permission denied */);
|
throw new SocketException(10013 /* Permission denied */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MONO_INCOMPATIBLE
|
||||||
_socket.Bind(new IPEndPoint(IPAddress.IPv6Any, _port));
|
_socket.Bind(new IPEndPoint(IPAddress.IPv6Any, _port));
|
||||||
_socket.Listen(4);
|
_socket.Listen(100);
|
||||||
|
#else
|
||||||
|
_socket4.Bind(new IPEndPoint(IPAddress.Any, _port));
|
||||||
|
_socket4.Listen(100);
|
||||||
|
|
||||||
|
_socket6.Bind(new IPEndPoint(IPAddress.IPv6Any, _port));
|
||||||
|
_socket6.Listen(100);
|
||||||
|
#endif
|
||||||
|
|
||||||
Task.Factory.StartNew(() =>
|
Task.Factory.StartNew(() =>
|
||||||
{
|
{
|
||||||
_log.Debug("Listener loop started");
|
_log.Debug("Listener loop started");
|
||||||
|
#if MONO_INCOMPATIBLE
|
||||||
|
var socket = _socket;
|
||||||
|
#else
|
||||||
|
var socket = _socket4;
|
||||||
|
#endif
|
||||||
var allDone = new ManualResetEvent(false);
|
var allDone = new ManualResetEvent(false);
|
||||||
while (_socket != null && _socket.IsBound)
|
while (
|
||||||
|
#if MONO_INCOMPATIBLE
|
||||||
|
_socket != null && _socket.IsBound
|
||||||
|
#else
|
||||||
|
_socket4 != null && _socket4.IsBound
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
allDone.Reset();
|
allDone.Reset();
|
||||||
_socket.BeginAccept(ar =>
|
socket.BeginAccept(ar =>
|
||||||
{
|
{
|
||||||
_log.Debug("Async accept client start");
|
_log.Debug("Async accept client start");
|
||||||
allDone.Set();
|
allDone.Set();
|
||||||
|
@ -112,12 +148,41 @@ namespace NPSharp.NP
|
||||||
_log.Debug("Async accept client end");
|
_log.Debug("Async accept client end");
|
||||||
|
|
||||||
_handleClient(npsc);
|
_handleClient(npsc);
|
||||||
}, _socket);
|
}, socket);
|
||||||
allDone.WaitOne();
|
allDone.WaitOne();
|
||||||
}
|
}
|
||||||
_log.Debug("Listener loop shut down");
|
_log.Debug("Listener loop shut down");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#if !MONO_INCOMPATIBLE
|
||||||
|
Task.Factory.StartNew(() =>
|
||||||
|
{
|
||||||
|
_log.Debug("Listener loop (IPv6) started");
|
||||||
|
|
||||||
|
var allDone = new ManualResetEvent(false);
|
||||||
|
while (_socket6 != null && _socket6.IsBound)
|
||||||
|
{
|
||||||
|
allDone.Reset();
|
||||||
|
_socket6.BeginAccept(ar =>
|
||||||
|
{
|
||||||
|
_log.Debug("Async accept (IPv6) client start");
|
||||||
|
allDone.Set();
|
||||||
|
|
||||||
|
var serverSocket = (Socket)ar.AsyncState;
|
||||||
|
var clientSocket = serverSocket.EndAccept(ar);
|
||||||
|
|
||||||
|
var npsc = new NPServerClient(this, new RPCServerStream(clientSocket));
|
||||||
|
|
||||||
|
_log.Debug("Async accept (IPv6) client end");
|
||||||
|
|
||||||
|
_handleClient(npsc);
|
||||||
|
}, _socket6);
|
||||||
|
allDone.WaitOne();
|
||||||
|
}
|
||||||
|
_log.Debug("Listener loop (IPv6) shut down");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shuts down all connections and stops the NP server.
|
/// Shuts down all connections and stops the NP server.
|
||||||
|
@ -125,7 +190,12 @@ namespace NPSharp.NP
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
// TODO: Wait for sockets to COMPLETELY shut down
|
// TODO: Wait for sockets to COMPLETELY shut down
|
||||||
|
#if MONO_INCOMPATIBLE
|
||||||
_socket.Shutdown(SocketShutdown.Both);
|
_socket.Shutdown(SocketShutdown.Both);
|
||||||
|
#else
|
||||||
|
_socket4.Shutdown(SocketShutdown.Both);
|
||||||
|
_socket6.Shutdown(SocketShutdown.Both);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void _handleClient(NPServerClient client)
|
internal void _handleClient(NPServerClient client)
|
||||||
|
|
Loading…
Reference in New Issue