diff --git a/Lidgren.Network/NetPeer.Internal.cs b/Lidgren.Network/NetPeer.Internal.cs index fc378cd..162e681 100644 --- a/Lidgren.Network/NetPeer.Internal.cs +++ b/Lidgren.Network/NetPeer.Internal.cs @@ -4,12 +4,12 @@ using System.Threading; using System.Diagnostics; using System.Security.Cryptography; using System.Net.Sockets; -using System.Collections.Generic; - +using System.Collections.Generic; + #if !__NOIPENDPOINT__ -using NetEndPoint = System.Net.IPEndPoint; +using NetEndPoint = System.Net.IPEndPoint; #endif - + namespace Lidgren.Network { public partial class NetPeer @@ -39,13 +39,13 @@ namespace Lidgren.Network internal bool m_executeFlushSendQueue; private AutoResetEvent m_messageReceivedEvent; - private List> m_receiveCallbacks; - + private List> m_receiveCallbacks; + /// /// Gets the socket, if Start() has been called /// - public Socket Socket { get { return m_socket; } } - + public Socket Socket { get { return m_socket; } } + /// /// Call this to register a callback for when a new message arrives /// @@ -58,18 +58,18 @@ namespace Lidgren.Network if (m_receiveCallbacks == null) m_receiveCallbacks = new List>(); m_receiveCallbacks.Add(new NetTuple(syncContext, callback)); - } - + } + /// /// Call this to unregister a callback, but remember to do it in the same synchronization context! /// public void UnregisterReceivedCallback(SendOrPostCallback callback) { if (m_receiveCallbacks == null) - return; - - // remove all callbacks regardless of sync context - m_receiveCallbacks.RemoveAll(tuple => tuple.Item2.Equals(callback)); + return; + + // remove all callbacks regardless of sync context + m_receiveCallbacks.RemoveAll(tuple => tuple.Item2.Equals(callback)); if (m_receiveCallbacks.Count < 1) m_receiveCallbacks = null; @@ -112,44 +112,45 @@ namespace Lidgren.Network if (now - m_lastSocketBind < 1.0) { LogDebug("Suppressed socket rebind; last bound " + (now - m_lastSocketBind) + " seconds ago"); - return; // only allow rebind once every second + return; // only allow rebind once every second } m_lastSocketBind = now; - if (m_socket == null) - m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - - if (reBind) - m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1); - - m_socket.ReceiveBufferSize = m_configuration.ReceiveBufferSize; - m_socket.SendBufferSize = m_configuration.SendBufferSize; - m_socket.Blocking = false; - - var ep = (EndPoint)new NetEndPoint(m_configuration.LocalAddress, reBind ? m_listenPort : m_configuration.Port); - m_socket.Bind(ep); - - // try catch only works on linux not osx - try - { - // this is not supported in mono / mac or linux yet. - if(Environment.OSVersion.Platform != PlatformID.Unix) - { - const uint IOC_IN = 0x80000000; - const uint IOC_VENDOR = 0x18000000; - uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; - m_socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null); - } - else - { - LogDebug("Platform doesn't support SIO_UDP_CONNRESET"); - } - } - catch (System.Exception e) + using (var mutex = new Mutex(false, "Global\\lidgrenSocketBind")) { - LogDebug("Platform doesn't support SIO_UDP_CONNRESET"); - // this will be thrown on linux but not mac if it doesn't exist. - // ignore; SIO_UDP_CONNRESET not supported on this platform + try + { + mutex.WaitOne(); + + if (m_socket == null) + m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + + if (reBind) + m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1); + + m_socket.ReceiveBufferSize = m_configuration.ReceiveBufferSize; + m_socket.SendBufferSize = m_configuration.SendBufferSize; + m_socket.Blocking = false; + + var ep = (EndPoint)new NetEndPoint(m_configuration.LocalAddress, reBind ? m_listenPort : m_configuration.Port); + m_socket.Bind(ep); + + try + { + const uint IOC_IN = 0x80000000; + const uint IOC_VENDOR = 0x18000000; + uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; + m_socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null); + } + catch + { + // ignore; SIO_UDP_CONNRESET not supported on this platform + } + } + finally + { + mutex.ReleaseMutex(); + } } var boundEp = m_socket.LocalEndPoint as NetEndPoint;