1
0
mirror of https://github.com/lidgren/lidgren-network-gen3.git synced 2026-05-19 00:26:30 +09:00

initializing network (including binding to socket) moved out from network thread, enabling catching of exceptions

ConnectionReset on reading handled properly (by disconnecting) when only one connection
readonly added to various members
This commit is contained in:
lidgren
2010-08-11 18:34:15 +00:00
parent 4fef27d175
commit 38bb13b3a7
11 changed files with 83 additions and 93 deletions

View File

@@ -149,7 +149,7 @@ namespace Lidgren.Network
return; return;
} }
private void FinishDisconnect() internal void FinishDisconnect()
{ {
m_owner.VerifyNetworkThread(); m_owner.VerifyNetworkThread();

View File

@@ -25,8 +25,8 @@ namespace Lidgren.Network
{ {
public partial class NetConnection public partial class NetConnection
{ {
private int[] m_nextSendSequenceNumber; private readonly int[] m_nextSendSequenceNumber;
private ushort[] m_lastReceivedSequenced; private readonly ushort[] m_lastReceivedSequenced;
internal readonly List<NetSending> m_unackedSends = new List<NetSending>(); internal readonly List<NetSending> m_unackedSends = new List<NetSending>();
@@ -57,17 +57,7 @@ namespace Lidgren.Network
} }
return retval; 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) internal ushort GetSendSequenceNumber(NetMessageType mtp)
{ {
if (mtp < NetMessageType.UserSequenced) if (mtp < NetMessageType.UserSequenced)

View File

@@ -38,12 +38,12 @@ namespace Lidgren.Network
internal NetConnectionStatus m_visibleStatus; internal NetConnectionStatus m_visibleStatus;
private double m_lastSentUnsentMessages; private double m_lastSentUnsentMessages;
private float m_throttleDebt; private float m_throttleDebt;
private NetPeerConfiguration m_peerConfiguration; private readonly NetPeerConfiguration m_peerConfiguration;
internal NetConnectionStatistics m_statistics; internal NetConnectionStatistics m_statistics;
private int m_lesserHeartbeats; private int m_lesserHeartbeats;
private int m_nextFragmentGroupId; private int m_nextFragmentGroupId;
internal long m_remoteUniqueIdentifier; internal long m_remoteUniqueIdentifier;
private Dictionary<int, NetIncomingMessage> m_fragmentGroups; private readonly Dictionary<int, NetIncomingMessage> m_fragmentGroups;
private int m_handshakeAttempts; private int m_handshakeAttempts;
internal PendingConnectionStatus m_pendingStatus = PendingConnectionStatus.NotPending; internal PendingConnectionStatus m_pendingStatus = PendingConnectionStatus.NotPending;
@@ -99,7 +99,13 @@ namespace Lidgren.Network
m_lastSendRespondedTo = now; m_lastSendRespondedTo = now;
m_statistics = new NetConnectionStatistics(this); 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 // 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) if (send.MessageType == NetMessageType.Library && msg.m_libType == NetMessageLibraryType.Disconnect)
{ {
FinishDisconnect(); FinishDisconnect();
@@ -706,6 +713,9 @@ namespace Lidgren.Network
m_owner.LogVerbose("Disconnect requested for " + this); m_owner.LogVerbose("Disconnect requested for " + this);
m_disconnectByeMessage = byeMessage; m_disconnectByeMessage = byeMessage;
if (m_status != NetConnectionStatus.Disconnected && m_status != NetConnectionStatus.None)
SetStatus(NetConnectionStatus.Disconnecting, byeMessage);
// loosen up throttling // loosen up throttling
m_throttleDebt = -m_owner.m_configuration.m_throttlePeakBytes; m_throttleDebt = -m_owner.m_configuration.m_throttlePeakBytes;

View File

@@ -216,14 +216,14 @@ namespace Lidgren.Network
/// </summary> /// </summary>
public static byte[] ComputeClientPublicKey(byte[] clientPrivateKey) // a 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()); 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())); Console.WriteLine("A: " + NetUtility.ToHexString(retval.GetBytes()));
return retval.GetBytes(); return retval.GetBytes();

View File

@@ -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 const string c_readOverflowError = "Trying to read past the buffer size - likely caused by mismatching Write/Reads, different size or order.";
private static Dictionary<Type, MethodInfo> s_readMethods; private static readonly Dictionary<Type, MethodInfo> s_readMethods;
private int m_readPosition; private int m_readPosition;

View File

@@ -64,6 +64,8 @@ namespace Lidgren.Network
{ {
LogWarning("Pending connection still in pending state after 10 seconds; forgot to Approve/Deny?"); LogWarning("Pending connection still in pending state after 10 seconds; forgot to Approve/Deny?");
m_pendingConnections.Remove(conn); m_pendingConnections.Remove(conn);
if (m_pendingConnections.Count < 1)
m_pendingConnections = null;
return; return;
} }
break; break;
@@ -71,12 +73,16 @@ namespace Lidgren.Network
// accept connection // accept connection
AcceptConnection(conn); AcceptConnection(conn);
m_pendingConnections.Remove(conn); m_pendingConnections.Remove(conn);
if (m_pendingConnections.Count < 1)
m_pendingConnections = null;
return; return;
case PendingConnectionStatus.Denied: case PendingConnectionStatus.Denied:
// send disconnected // send disconnected
NetOutgoingMessage bye = CreateLibraryMessage(NetMessageLibraryType.Disconnect, conn.m_pendingDenialReason); NetOutgoingMessage bye = CreateLibraryMessage(NetMessageLibraryType.Disconnect, conn.m_pendingDenialReason);
SendUnconnectedLibrary(bye, conn.m_remoteEndpoint); SendUnconnectedLibrary(bye, conn.m_remoteEndpoint);
m_pendingConnections.Remove(conn); m_pendingConnections.Remove(conn);
if (m_pendingConnections.Count < 1)
m_pendingConnections = null;
return; return;
} }
} }

View File

@@ -70,12 +70,11 @@ namespace Lidgren.Network
// //
// Network loop // Network loop
// //
private void Run() private void InitializeNetwork()
{ {
// //
// Initialize // Initialize
// //
VerifyNetworkThread();
InitializeRecycling(); InitializeRecycling();
@@ -94,8 +93,7 @@ namespace Lidgren.Network
// random bytes is better than nothing // random bytes is better than nothing
NetRandom.Instance.NextBytes(m_macAddressBytes); NetRandom.Instance.NextBytes(m_macAddressBytes);
#endif #endif
LogDebug("Initializing Network");
LogDebug("Network thread started");
lock (m_initializeLock) lock (m_initializeLock)
{ {
@@ -106,77 +104,50 @@ namespace Lidgren.Network
// bind to socket // bind to socket
IPEndPoint iep = null; 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); iep = new IPEndPoint(m_configuration.LocalAddress, m_configuration.Port);
m_socket.ReceiveBufferSize = m_configuration.ReceiveBufferSize; EndPoint ep = (EndPoint)iep;
m_socket.SendBufferSize = m_configuration.SendBufferSize;
m_socket.Blocking = false;
m_socket.Bind(ep);
IPEndPoint boundEp = m_socket.LocalEndPoint as IPEndPoint; m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
LogDebug("Socket bound to " + boundEp + ": " + m_socket.IsBound); 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()); m_listenPort = boundEp.Port;
int second = boundEp.GetHashCode();
byte[] raw = new byte[8]; int first = (pa == null ? this.GetHashCode() : pa.GetHashCode());
raw[0] = (byte)first; int second = boundEp.GetHashCode();
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);
m_receiveBuffer = new byte[m_configuration.ReceiveBufferSize]; byte[] raw = new byte[8];
m_sendBuffer = new byte[m_configuration.SendBufferSize]; 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_receiveBuffer = new byte[m_configuration.ReceiveBufferSize];
m_status = NetPeerStatus.Running; m_sendBuffer = new byte[m_configuration.SendBufferSize];
LogVerbose("Initialization done"); 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;
if (sex.SocketErrorCode == SocketError.AddressAlreadyInUse) // only set Running if everything succeeds
LogError("Failed to bind to port " + (iep == null ? "Null" : iep.ToString()) + " - Address already in use!"); m_status = NetPeerStatus.Running;
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
} }
}
private void NetworkLoop()
{
VerifyNetworkThread();
LogDebug("Network thread started");
// //
// Network loop // Network loop
@@ -329,6 +300,17 @@ namespace Lidgren.Network
// connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable" // 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?! // 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); //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; return;
} }

View File

@@ -26,9 +26,9 @@ namespace Lidgren.Network
{ {
internal int m_storedBytes; internal int m_storedBytes;
private int m_maxStoredBytes; private int m_maxStoredBytes;
private List<byte[]> m_storagePool = new List<byte[]>(); private readonly List<byte[]> m_storagePool = new List<byte[]>();
private NetQueue<NetIncomingMessage> m_incomingMessagesPool = new NetQueue<NetIncomingMessage>(16); private readonly NetQueue<NetIncomingMessage> m_incomingMessagesPool = new NetQueue<NetIncomingMessage>(16);
private NetQueue<NetOutgoingMessage> m_outgoingMessagesPool = new NetQueue<NetOutgoingMessage>(16); private readonly NetQueue<NetOutgoingMessage> m_outgoingMessagesPool = new NetQueue<NetOutgoingMessage>(16);
private void InitializeRecycling() private void InitializeRecycling()
{ {

View File

@@ -140,14 +140,16 @@ namespace Lidgren.Network
m_configuration.VerifyAndLock(); m_configuration.VerifyAndLock();
InitializeNetwork();
// start network thread // 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.Name = "Lidgren network thread";
m_networkThread.IsBackground = true; m_networkThread.IsBackground = true;
m_networkThread.Start(); m_networkThread.Start();
// allow some time for network thread to start up in case they call Connect() immediately // allow some time for network thread to start up in case they call Connect() immediately
Thread.Sleep(3); Thread.Sleep(10);
} }
/// <summary> /// <summary>

View File

@@ -64,7 +64,7 @@ namespace ChatClient
NetOutgoingMessage om = Client.CreateMessage(); NetOutgoingMessage om = Client.CreateMessage();
om.WriteAllFields(cm); om.WriteAllFields(cm);
Client.SendMessage(om, NetDeliveryMethod.ReliableOrdered, 8); Client.SendMessage(om, NetDeliveryMethod.ReliableOrdered, 1);
} }
static void AppLoop(object sender, EventArgs e) static void AppLoop(object sender, EventArgs e)

View File

@@ -79,7 +79,7 @@ namespace ChatServer
NetOutgoingMessage om = Server.CreateMessage(); NetOutgoingMessage om = Server.CreateMessage();
om.WriteAllProperties(cm, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); 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); Server.SendMessage(om, Server.Connections, NetDeliveryMethod.ReliableOrdered, 0);
break; break;