diff --git a/Lidgren.Network/NetConnection.Handshake.cs b/Lidgren.Network/NetConnection.Handshake.cs index 6cb5679..c087a15 100644 --- a/Lidgren.Network/NetConnection.Handshake.cs +++ b/Lidgren.Network/NetConnection.Handshake.cs @@ -149,7 +149,7 @@ namespace Lidgren.Network return; } - private void FinishDisconnect() + internal void FinishDisconnect() { m_owner.VerifyNetworkThread(); diff --git a/Lidgren.Network/NetConnection.Reliability.cs b/Lidgren.Network/NetConnection.Reliability.cs index d595cec..a3c84bf 100644 --- a/Lidgren.Network/NetConnection.Reliability.cs +++ b/Lidgren.Network/NetConnection.Reliability.cs @@ -25,8 +25,8 @@ namespace Lidgren.Network { public partial class NetConnection { - private int[] m_nextSendSequenceNumber; - private ushort[] m_lastReceivedSequenced; + private readonly int[] m_nextSendSequenceNumber; + private readonly ushort[] m_lastReceivedSequenced; internal readonly List m_unackedSends = new List(); @@ -57,17 +57,7 @@ namespace Lidgren.Network } return retval; } - - private void InitializeReliability() - { - int num = ((int)NetMessageType.UserReliableOrdered + NetConstants.NetChannelsPerDeliveryMethod) - (int)NetMessageType.UserSequenced; - m_nextSendSequenceNumber = new int[num]; - m_lastReceivedSequenced = new ushort[num]; - for (int i = 0; i < m_lastReceivedSequenced.Length; i++) - m_lastReceivedSequenced[i] = ushort.MaxValue; - m_nextForceAckTime = double.MaxValue; - } - + internal ushort GetSendSequenceNumber(NetMessageType mtp) { if (mtp < NetMessageType.UserSequenced) diff --git a/Lidgren.Network/NetConnection.cs b/Lidgren.Network/NetConnection.cs index dc0b2e7..6f7b187 100644 --- a/Lidgren.Network/NetConnection.cs +++ b/Lidgren.Network/NetConnection.cs @@ -38,12 +38,12 @@ namespace Lidgren.Network internal NetConnectionStatus m_visibleStatus; private double m_lastSentUnsentMessages; private float m_throttleDebt; - private NetPeerConfiguration m_peerConfiguration; + private readonly NetPeerConfiguration m_peerConfiguration; internal NetConnectionStatistics m_statistics; private int m_lesserHeartbeats; private int m_nextFragmentGroupId; internal long m_remoteUniqueIdentifier; - private Dictionary m_fragmentGroups; + private readonly Dictionary m_fragmentGroups; private int m_handshakeAttempts; internal PendingConnectionStatus m_pendingStatus = PendingConnectionStatus.NotPending; @@ -99,7 +99,13 @@ namespace Lidgren.Network m_lastSendRespondedTo = now; m_statistics = new NetConnectionStatistics(this); - InitializeReliability(); + //InitializeReliability(); + int num = ((int)NetMessageType.UserReliableOrdered + NetConstants.NetChannelsPerDeliveryMethod) - (int)NetMessageType.UserSequenced; + m_nextSendSequenceNumber = new int[num]; + m_lastReceivedSequenced = new ushort[num]; + for (int i = 0; i < m_lastReceivedSequenced.Length; i++) + m_lastReceivedSequenced[i] = ushort.MaxValue; + m_nextForceAckTime = double.MaxValue; } // run on network thread @@ -286,6 +292,7 @@ namespace Lidgren.Network } } + // when sending disconnect we can finish our own disconnect if (send.MessageType == NetMessageType.Library && msg.m_libType == NetMessageLibraryType.Disconnect) { FinishDisconnect(); @@ -706,6 +713,9 @@ namespace Lidgren.Network m_owner.LogVerbose("Disconnect requested for " + this); m_disconnectByeMessage = byeMessage; + if (m_status != NetConnectionStatus.Disconnected && m_status != NetConnectionStatus.None) + SetStatus(NetConnectionStatus.Disconnecting, byeMessage); + // loosen up throttling m_throttleDebt = -m_owner.m_configuration.m_throttlePeakBytes; diff --git a/Lidgren.Network/NetEncryption.cs b/Lidgren.Network/NetEncryption.cs index 482cf36..8e004d7 100644 --- a/Lidgren.Network/NetEncryption.cs +++ b/Lidgren.Network/NetEncryption.cs @@ -216,14 +216,14 @@ namespace Lidgren.Network /// public static byte[] ComputeClientPublicKey(byte[] clientPrivateKey) // a { - BigInteger salt = new BigInteger(clientPrivateKey); + BigInteger a = new BigInteger(clientPrivateKey); - BigInteger retval = g.ModPow(salt, N); + BigInteger retval = g.ModPow(a, N); string gs = NetUtility.ToHexString(g.GetBytes()); - Console.WriteLine("SALT: " + NetUtility.ToHexString(salt.GetBytes())); + Console.WriteLine("a: " + NetUtility.ToHexString(a.GetBytes())); Console.WriteLine("A: " + NetUtility.ToHexString(retval.GetBytes())); return retval.GetBytes(); diff --git a/Lidgren.Network/NetIncomingMessage.Read.cs b/Lidgren.Network/NetIncomingMessage.Read.cs index 297f8a5..d652dd0 100644 --- a/Lidgren.Network/NetIncomingMessage.Read.cs +++ b/Lidgren.Network/NetIncomingMessage.Read.cs @@ -28,7 +28,7 @@ namespace Lidgren.Network { private const string c_readOverflowError = "Trying to read past the buffer size - likely caused by mismatching Write/Reads, different size or order."; - private static Dictionary s_readMethods; + private static readonly Dictionary s_readMethods; private int m_readPosition; diff --git a/Lidgren.Network/NetPeer.ConnectionApproval.cs b/Lidgren.Network/NetPeer.ConnectionApproval.cs index f5160b9..8436bfc 100644 --- a/Lidgren.Network/NetPeer.ConnectionApproval.cs +++ b/Lidgren.Network/NetPeer.ConnectionApproval.cs @@ -64,6 +64,8 @@ namespace Lidgren.Network { LogWarning("Pending connection still in pending state after 10 seconds; forgot to Approve/Deny?"); m_pendingConnections.Remove(conn); + if (m_pendingConnections.Count < 1) + m_pendingConnections = null; return; } break; @@ -71,12 +73,16 @@ namespace Lidgren.Network // accept connection AcceptConnection(conn); m_pendingConnections.Remove(conn); + if (m_pendingConnections.Count < 1) + m_pendingConnections = null; return; case PendingConnectionStatus.Denied: // send disconnected NetOutgoingMessage bye = CreateLibraryMessage(NetMessageLibraryType.Disconnect, conn.m_pendingDenialReason); SendUnconnectedLibrary(bye, conn.m_remoteEndpoint); m_pendingConnections.Remove(conn); + if (m_pendingConnections.Count < 1) + m_pendingConnections = null; return; } } diff --git a/Lidgren.Network/NetPeer.Internal.cs b/Lidgren.Network/NetPeer.Internal.cs index 782b01b..63d4542 100644 --- a/Lidgren.Network/NetPeer.Internal.cs +++ b/Lidgren.Network/NetPeer.Internal.cs @@ -70,12 +70,11 @@ namespace Lidgren.Network // // Network loop // - private void Run() + private void InitializeNetwork() { // // Initialize // - VerifyNetworkThread(); InitializeRecycling(); @@ -94,8 +93,7 @@ namespace Lidgren.Network // random bytes is better than nothing NetRandom.Instance.NextBytes(m_macAddressBytes); #endif - - LogDebug("Network thread started"); + LogDebug("Initializing Network"); lock (m_initializeLock) { @@ -106,77 +104,50 @@ namespace Lidgren.Network // bind to socket IPEndPoint iep = null; - try - { - iep = new IPEndPoint(m_configuration.LocalAddress, m_configuration.Port); - EndPoint ep = (EndPoint)iep; - m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - m_socket.ReceiveBufferSize = m_configuration.ReceiveBufferSize; - m_socket.SendBufferSize = m_configuration.SendBufferSize; - m_socket.Blocking = false; - m_socket.Bind(ep); + iep = new IPEndPoint(m_configuration.LocalAddress, m_configuration.Port); + EndPoint ep = (EndPoint)iep; - IPEndPoint boundEp = m_socket.LocalEndPoint as IPEndPoint; - LogDebug("Socket bound to " + boundEp + ": " + m_socket.IsBound); + m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + m_socket.ReceiveBufferSize = m_configuration.ReceiveBufferSize; + m_socket.SendBufferSize = m_configuration.SendBufferSize; + m_socket.Blocking = false; + m_socket.Bind(ep); - m_listenPort = boundEp.Port; + IPEndPoint boundEp = m_socket.LocalEndPoint as IPEndPoint; + LogDebug("Socket bound to " + boundEp + ": " + m_socket.IsBound); - int first = (pa == null ? this.GetHashCode() : pa.GetHashCode()); - int second = boundEp.GetHashCode(); + m_listenPort = boundEp.Port; - byte[] raw = new byte[8]; - raw[0] = (byte)first; - raw[1] = (byte)(first << 8); - raw[2] = (byte)(first << 16); - raw[3] = (byte)(first << 24); - raw[4] = (byte)second; - raw[5] = (byte)(second << 8); - raw[6] = (byte)(second << 16); - raw[7] = (byte)(second << 24); - m_uniqueIdentifier = BitConverter.ToInt64(NetSha.Hash(raw), 0); + int first = (pa == null ? this.GetHashCode() : pa.GetHashCode()); + int second = boundEp.GetHashCode(); - m_receiveBuffer = new byte[m_configuration.ReceiveBufferSize]; - m_sendBuffer = new byte[m_configuration.SendBufferSize]; + byte[] raw = new byte[8]; + raw[0] = (byte)first; + raw[1] = (byte)(first << 8); + raw[2] = (byte)(first << 16); + raw[3] = (byte)(first << 24); + raw[4] = (byte)second; + raw[5] = (byte)(second << 8); + raw[6] = (byte)(second << 16); + raw[7] = (byte)(second << 24); + m_uniqueIdentifier = BitConverter.ToInt64(NetSha.Hash(raw), 0); - // only set Running if everything succeeds - m_status = NetPeerStatus.Running; + m_receiveBuffer = new byte[m_configuration.ReceiveBufferSize]; + m_sendBuffer = new byte[m_configuration.SendBufferSize]; - LogVerbose("Initialization done"); - } -#if DEBUG - catch(Exception) - { - throw; - } -#else - catch (SocketException sex) - { - // catastrophic failure; we can't know what's been initialized, try to back out - m_status = NetPeerStatus.NotRunning; + LogVerbose("Initialization done"); - if (sex.SocketErrorCode == SocketError.AddressAlreadyInUse) - LogError("Failed to bind to port " + (iep == null ? "Null" : iep.ToString()) + " - Address already in use!"); - else - LogError(sex.Message); - LogError("Lidgren could not initialize properly; please call Start() again"); - - // exit thread - return; - } - catch (Exception ex) - { - // catastrophic failure; we can't know what's been initialized, try to back out - m_status = NetPeerStatus.NotRunning; - - LogError(ex.Message); - LogError("Lidgren could not initialize properly; please call Start() again"); - - // exit thread - return; - } -#endif + // only set Running if everything succeeds + m_status = NetPeerStatus.Running; } + } + + private void NetworkLoop() + { + VerifyNetworkThread(); + + LogDebug("Network thread started"); // // Network loop @@ -329,6 +300,17 @@ namespace Lidgren.Network // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable" // we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?! //LogWarning("Connection reset by peer, seemingly from " + m_senderRemote); + lock (m_connections) + { + if (m_connections.Count == 1) + { + // only one connection; let's shut it down, unless already in progress + m_connections[0].Disconnect("Connection forcibly closed"); + m_connections[0].ExecuteDisconnect(false); + m_connections[0].FinishDisconnect(); + } + } + return; } diff --git a/Lidgren.Network/NetPeer.Recycling.cs b/Lidgren.Network/NetPeer.Recycling.cs index 7dbf768..674b9b9 100644 --- a/Lidgren.Network/NetPeer.Recycling.cs +++ b/Lidgren.Network/NetPeer.Recycling.cs @@ -26,9 +26,9 @@ namespace Lidgren.Network { internal int m_storedBytes; private int m_maxStoredBytes; - private List m_storagePool = new List(); - private NetQueue m_incomingMessagesPool = new NetQueue(16); - private NetQueue m_outgoingMessagesPool = new NetQueue(16); + private readonly List m_storagePool = new List(); + private readonly NetQueue m_incomingMessagesPool = new NetQueue(16); + private readonly NetQueue m_outgoingMessagesPool = new NetQueue(16); private void InitializeRecycling() { diff --git a/Lidgren.Network/NetPeer.cs b/Lidgren.Network/NetPeer.cs index 46161bb..b301cd1 100644 --- a/Lidgren.Network/NetPeer.cs +++ b/Lidgren.Network/NetPeer.cs @@ -140,14 +140,16 @@ namespace Lidgren.Network m_configuration.VerifyAndLock(); + InitializeNetwork(); + // start network thread - m_networkThread = new Thread(new ThreadStart(Run)); + m_networkThread = new Thread(new ThreadStart(NetworkLoop)); m_networkThread.Name = "Lidgren network thread"; m_networkThread.IsBackground = true; m_networkThread.Start(); // allow some time for network thread to start up in case they call Connect() immediately - Thread.Sleep(3); + Thread.Sleep(10); } /// diff --git a/Samples/ChatClient/Program.cs b/Samples/ChatClient/Program.cs index 89f6f48..f87686f 100644 --- a/Samples/ChatClient/Program.cs +++ b/Samples/ChatClient/Program.cs @@ -64,7 +64,7 @@ namespace ChatClient NetOutgoingMessage om = Client.CreateMessage(); om.WriteAllFields(cm); - Client.SendMessage(om, NetDeliveryMethod.ReliableOrdered, 8); + Client.SendMessage(om, NetDeliveryMethod.ReliableOrdered, 1); } static void AppLoop(object sender, EventArgs e) diff --git a/Samples/ChatServer/Program.cs b/Samples/ChatServer/Program.cs index de90af4..320d195 100644 --- a/Samples/ChatServer/Program.cs +++ b/Samples/ChatServer/Program.cs @@ -79,7 +79,7 @@ namespace ChatServer NetOutgoingMessage om = Server.CreateMessage(); om.WriteAllProperties(cm, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); - Display("Forwarding text from " + cm.Sender + " to all clients: " + cm.Text); + Display("Forwarding text from " + cm.Sender + " (seqchan " + msg.SequenceChannel + ") to all clients: " + cm.Text); Server.SendMessage(om, Server.Connections, NetDeliveryMethod.ReliableOrdered, 0); break;