private void InitializeNetwork() { lock (m_initializeLock) { // make sure this is properly set up again, if required. // start network thread if not running NetPeerManager.StartNetworkThread(); m_configuration.Lock(); if (m_status == NetPeerStatus.Running) { return; } if (m_configuration.m_enableUPnP) { m_upnp = new NetUPnP(this); } InitializePools(); m_releasedIncomingMessages.Clear(); m_unsentUnconnectedMessages.Clear(); _handshakeManager.Handshakes.Clear(); // bind to socket BindSocket(false); m_receiveBuffer = new byte[m_configuration.ReceiveBufferSize]; m_sendBuffer = new byte[m_configuration.SendBufferSize]; m_readHelperMessage = new NetIncomingMessage(NetIncomingMessageType.Error); m_readHelperMessage.m_data = m_receiveBuffer; byte[] macBytes = NetUtility.GetMacAddressBytes(); var boundEp = m_socket.LocalEndPoint as NetEndPoint; byte[] epBytes = BitConverter.GetBytes(boundEp.GetHashCode()); byte[] combined = new byte[epBytes.Length + macBytes.Length]; Array.Copy(epBytes, 0, combined, 0, epBytes.Length); Array.Copy(macBytes, 0, combined, epBytes.Length, macBytes.Length); m_uniqueIdentifier = BitConverter.ToInt64(NetUtility.ComputeSHAHash(combined), 0); m_status = NetPeerStatus.Running; } }
public void ExecutePeerShutdown() { Console.WriteLine("Network shutdown enter"); // disconnect and make one final heartbeat var list = new List <NetConnection>(_handshakeManager.Handshakes.Count + m_connections.Count); lock (m_connections) { foreach (var conn in m_connections) { if (conn != null) { list.Add(conn); } } } foreach (var hs in _handshakeManager.Handshakes.Values) { if (hs != null && list.Contains(hs) == false) { list.Add(hs); } } // shut down connections foreach (NetConnection conn in list) { conn.Shutdown(m_shutdownReason); } FlushDelayedPackets(); // one final heartbeat, will send stuff and do disconnect PeerUpdate(); NetUtility.Sleep(10); lock (m_initializeLock) { try { if (m_socket != null) { try { // shutdown socket send and recieve handlers. m_socket.Shutdown(SocketShutdown.Both); } catch (Exception e) { LogDebug(e.ToString()); } finally { // close connection, if present m_socket.Close(2); } } } catch (Exception ex) { LogDebug("socket shutdown method exception: " + ex.ToString()); throw; } finally { NetPeerManager.RemovePeer(this); // wake up any threads waiting for server shutdown m_messageReceivedEvent?.Set(); m_lastSocketBind = float.MinValue; m_receiveBuffer = null; m_sendBuffer = null; m_unsentUnconnectedMessages?.Clear(); m_connections?.Clear(); m_connectionLookup?.Clear(); _handshakeManager.Handshakes?.Clear(); _handshakeManager = null; m_status = NetPeerStatus.NotRunning; LogDebug("Shutdown complete"); Console.WriteLine("Shutdown network peer properly"); } } return; }
/// <summary> /// Bind socket - with rebind parameter for when you need to rebind a socket /// </summary> /// <param name="rebind"></param> private void BindSocket(bool rebind) { double now = NetTime.Now; if (now - m_lastSocketBind < 1.0) { LogDebug("Suppressed socket rebind; last bound " + (now - m_lastSocketBind) + " seconds ago"); return; // only allow rebind once every second } m_lastSocketBind = now; if (m_socket == null) { m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); } // todo: write unit test which executes rebinding of the sockets on android and ios if (rebind) { m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1); } // Register this peer to our manager NetPeerManager.AddPeer(this); 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) { 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 } var boundEp = m_socket.LocalEndPoint as NetEndPoint; LogDebug("Socket bound to " + boundEp + ": " + m_socket.IsBound); m_listenPort = boundEp.Port; }