You've already forked lidgren-network-gen3
mirror of
https://github.com/lidgren/lidgren-network-gen3.git
synced 2026-05-18 16:16:35 +09:00
NetIncomingMessage.Clone added
Attempt to handle connection reset correctly when sending
This commit is contained in:
@@ -207,7 +207,16 @@ namespace Lidgren.Network
|
|||||||
if (ptr > 0 && (ptr + NetPeer.kMaxPacketHeaderSize + msgPayloadLength) > mtu)
|
if (ptr > 0 && (ptr + NetPeer.kMaxPacketHeaderSize + msgPayloadLength) > mtu)
|
||||||
{
|
{
|
||||||
// send packet and start new packet
|
// send packet and start new packet
|
||||||
m_owner.SendPacket(ptr, m_remoteEndpoint, numIncludedMessages);
|
bool connectionReset;
|
||||||
|
m_owner.SendPacket(ptr, m_remoteEndpoint, numIncludedMessages, out connectionReset);
|
||||||
|
if (connectionReset)
|
||||||
|
{
|
||||||
|
// ouch! can't sent any more; lets disconnect
|
||||||
|
Disconnect(NetConstants.ConnResetMessage);
|
||||||
|
ptr = 0;
|
||||||
|
numIncludedMessages = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
m_statistics.PacketSent(ptr, numIncludedMessages);
|
m_statistics.PacketSent(ptr, numIncludedMessages);
|
||||||
numIncludedMessages = 0;
|
numIncludedMessages = 0;
|
||||||
m_throttleDebt += ptr;
|
m_throttleDebt += ptr;
|
||||||
@@ -247,10 +256,19 @@ namespace Lidgren.Network
|
|||||||
|
|
||||||
if (ptr > 0)
|
if (ptr > 0)
|
||||||
{
|
{
|
||||||
m_owner.SendPacket(ptr, m_remoteEndpoint, numIncludedMessages);
|
bool connectionReset;
|
||||||
m_statistics.PacketSent(ptr, numIncludedMessages);
|
m_owner.SendPacket(ptr, m_remoteEndpoint, numIncludedMessages, out connectionReset);
|
||||||
numIncludedMessages = 0;
|
if (connectionReset)
|
||||||
m_throttleDebt += ptr;
|
{
|
||||||
|
// ouch! can't sent any more; lets disconnect
|
||||||
|
Disconnect(NetConstants.ConnResetMessage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_statistics.PacketSent(ptr, numIncludedMessages);
|
||||||
|
numIncludedMessages = 0;
|
||||||
|
m_throttleDebt += ptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,5 +40,7 @@ namespace Lidgren.Network
|
|||||||
/// Number of bytes added when message is really a fragment
|
/// Number of bytes added when message is really a fragment
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal const int FragmentHeaderSize = 6;
|
internal const int FragmentHeaderSize = 6;
|
||||||
|
|
||||||
|
internal const string ConnResetMessage = "Connection was reset by remote host";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,14 +227,73 @@ namespace Lidgren.Network
|
|||||||
|
|
||||||
string one = NetUtility.ToHexString(A);
|
string one = NetUtility.ToHexString(A);
|
||||||
string two = NetUtility.ToHexString(B);
|
string two = NetUtility.ToHexString(B);
|
||||||
string compound = one + two.PadLeft(one.Length, '0');
|
string compound = one.PadLeft(64, '0') + two.PadLeft(64, '0');
|
||||||
byte[] cc = NetUtility.ToByteArray(compound);
|
byte[] cc = NetUtility.ToByteArray(compound);
|
||||||
|
|
||||||
return NetSha.Hash(cc);
|
return NetSha.Hash(cc);
|
||||||
|
|
||||||
|
//byte[] res = NetSha.Hash(cc);
|
||||||
|
//var resbig = new BigInteger(res);
|
||||||
|
//return BigInteger.Modulus(resbig, N).GetBytes();
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* SRP-3: u = first 32 bits (MSB) of SHA-1(B)
|
||||||
|
* SRP-6(a): u = SHA-1(A || B)
|
||||||
|
function srp_compute_u(Nv, av, bv) {
|
||||||
|
var ahex;
|
||||||
|
var bhex = String(bigInt2radix(bv, 16));
|
||||||
|
var hashin = "";
|
||||||
|
var utmp;
|
||||||
|
var nlen;
|
||||||
|
if(proto != "3") {
|
||||||
|
ahex = String(bigInt2radix(av, 16));
|
||||||
|
if(proto == "6") {
|
||||||
|
if((ahex.length & 1) == 0) {
|
||||||
|
hashin += ahex;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hashin += "0" + ahex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // 6a requires left-padding
|
||||||
|
nlen = 2 * ((Nv.bitLength() + 7) >> 3);
|
||||||
|
hashin += nzero(nlen - ahex.length) + ahex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(proto == "3" || proto == "6") {
|
||||||
|
if((bhex.length & 1) == 0) {
|
||||||
|
hashin += bhex;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hashin += "0" + bhex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // 6a requires left-padding; nlen already set above
|
||||||
|
hashin += nzero(nlen - bhex.length) + bhex;
|
||||||
|
}
|
||||||
|
if(proto == "3") {
|
||||||
|
utmp = parseBigInt(calcSHA1Hex(hashin).substr(0, 8), 16);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
utmp = parseBigInt(calcSHA1Hex(hashin), 16);
|
||||||
|
}
|
||||||
|
if(utmp.compareTo(Nv) < 0) {
|
||||||
|
return utmp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return utmp.mod(Nv.subtract(one));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public static byte[] ComputeClientToken(byte[] serverChallenge, byte[] x, byte[] u
|
public static byte[] ComputeClientToken(byte[] serverChallenge, byte[] x, byte[] u)
|
||||||
|
{
|
||||||
|
|
||||||
// S = (B - kg^x) ^ (a + ux) (mod N)
|
// S = (B - kg^x) ^ (a + ux) (mod N)
|
||||||
function srp_compute_client_S(BB, xx, uu, aa, kk) {
|
function srp_compute_client_S(BB, xx, uu, aa, kk) {
|
||||||
|
|||||||
@@ -130,6 +130,28 @@ namespace Lidgren.Network
|
|||||||
m_data = result;
|
m_data = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NetIncomingMessage Clone()
|
||||||
|
{
|
||||||
|
NetIncomingMessage retval = new NetIncomingMessage();
|
||||||
|
|
||||||
|
// copy content
|
||||||
|
retval.m_data = new byte[LengthBytes];
|
||||||
|
Buffer.BlockCopy(m_data, 0, retval.m_data, 0, LengthBytes);
|
||||||
|
|
||||||
|
retval.m_bitLength = m_bitLength;
|
||||||
|
retval.m_messageType = m_messageType;
|
||||||
|
retval.m_sequenceNumber = m_sequenceNumber;
|
||||||
|
retval.m_status = m_status;
|
||||||
|
retval.m_incomingType = m_incomingType;
|
||||||
|
retval.m_senderEndpoint = m_senderEndpoint;
|
||||||
|
retval.m_senderConnection = m_senderConnection;
|
||||||
|
retval.m_fragmentationInfo = m_fragmentationInfo;
|
||||||
|
retval.m_bitLength = m_bitLength;
|
||||||
|
retval.m_bitLength = m_bitLength;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return String.Format("[NetIncomingMessage {0}, {1}|{2}, {3} bits]",
|
return String.Format("[NetIncomingMessage {0}, {1}|{2}, {3} bits]",
|
||||||
|
|||||||
@@ -230,6 +230,7 @@ namespace Lidgren.Network
|
|||||||
//
|
//
|
||||||
|
|
||||||
int ptr = um.Encode(now, m_sendBuffer, 0, null);
|
int ptr = um.Encode(now, m_sendBuffer, 0, null);
|
||||||
|
bool connectionReset = false;
|
||||||
|
|
||||||
if (recipient.Address.Equals(IPAddress.Broadcast))
|
if (recipient.Address.Equals(IPAddress.Broadcast))
|
||||||
{
|
{
|
||||||
@@ -237,7 +238,7 @@ namespace Lidgren.Network
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
|
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
|
||||||
SendPacket(ptr, recipient, 1);
|
SendPacket(ptr, recipient, 1, out connectionReset);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -247,8 +248,11 @@ namespace Lidgren.Network
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// send normally
|
// send normally
|
||||||
SendPacket(ptr, recipient, 1);
|
SendPacket(ptr, recipient, 1, out connectionReset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (connectionReset)
|
||||||
|
LogWarning(NetConstants.ConnResetMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we need to reduce the recycled pool
|
// check if we need to reduce the recycled pool
|
||||||
@@ -276,9 +280,9 @@ namespace Lidgren.Network
|
|||||||
catch (SocketException sx)
|
catch (SocketException sx)
|
||||||
{
|
{
|
||||||
// no good response to this yet
|
// no good response to this yet
|
||||||
if (sx.ErrorCode == 10054)
|
if (sx.SocketErrorCode == SocketError.ConnectionReset)
|
||||||
{
|
{
|
||||||
// connection reset by peer, aka forcibly closed
|
// 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);
|
||||||
return;
|
return;
|
||||||
@@ -288,7 +292,7 @@ namespace Lidgren.Network
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytesReceived < 1)
|
if (bytesReceived < NetPeer.kMinPacketHeaderSize)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// renew current time; we might have waited in Poll
|
// renew current time; we might have waited in Poll
|
||||||
@@ -584,9 +588,13 @@ namespace Lidgren.Network
|
|||||||
int len = msg.Encode(now, m_sendBuffer, 0, conn);
|
int len = msg.Encode(now, m_sendBuffer, 0, conn);
|
||||||
Interlocked.Decrement(ref msg.m_inQueueCount);
|
Interlocked.Decrement(ref msg.m_inQueueCount);
|
||||||
|
|
||||||
SendPacket(len, conn.m_remoteEndpoint, 1);
|
bool connectionReset;
|
||||||
|
SendPacket(len, conn.m_remoteEndpoint, 1, out connectionReset);
|
||||||
|
|
||||||
Recycle(msg);
|
Recycle(msg);
|
||||||
|
|
||||||
|
if (connectionReset)
|
||||||
|
LogWarning("Connection was reset; remote host is not listening");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,8 +37,10 @@ namespace Lidgren.Network
|
|||||||
public IPEndPoint Target;
|
public IPEndPoint Target;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SendPacket(int numBytes, IPEndPoint target, int numMessages)
|
internal void SendPacket(int numBytes, IPEndPoint target, int numMessages, out bool connectionReset)
|
||||||
{
|
{
|
||||||
|
connectionReset = false;
|
||||||
|
|
||||||
// simulate loss
|
// simulate loss
|
||||||
float loss = m_configuration.m_loss;
|
float loss = m_configuration.m_loss;
|
||||||
if (loss > 0.0f)
|
if (loss > 0.0f)
|
||||||
@@ -59,7 +61,7 @@ namespace Lidgren.Network
|
|||||||
{
|
{
|
||||||
// no latency simulation
|
// no latency simulation
|
||||||
//LogVerbose("Sending packet " + numBytes + " bytes");
|
//LogVerbose("Sending packet " + numBytes + " bytes");
|
||||||
ActuallySendPacket(m_sendBuffer, numBytes, target);
|
ActuallySendPacket(m_sendBuffer, numBytes, target, out connectionReset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,26 +94,39 @@ namespace Lidgren.Network
|
|||||||
|
|
||||||
double now = NetTime.Now;
|
double now = NetTime.Now;
|
||||||
|
|
||||||
|
bool connectionReset;
|
||||||
|
|
||||||
RestartDelaySending:
|
RestartDelaySending:
|
||||||
foreach (DelayedPacket p in m_delayedPackets)
|
foreach (DelayedPacket p in m_delayedPackets)
|
||||||
{
|
{
|
||||||
if (now > p.DelayedUntil)
|
if (now > p.DelayedUntil)
|
||||||
{
|
{
|
||||||
ActuallySendPacket(p.Data, p.Data.Length, p.Target);
|
ActuallySendPacket(p.Data, p.Data.Length, p.Target, out connectionReset);
|
||||||
m_delayedPackets.Remove(p);
|
m_delayedPackets.Remove(p);
|
||||||
goto RestartDelaySending;
|
goto RestartDelaySending;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ActuallySendPacket(byte[] data, int numBytes, IPEndPoint target)
|
internal void ActuallySendPacket(byte[] data, int numBytes, IPEndPoint target, out bool connectionReset)
|
||||||
{
|
{
|
||||||
|
connectionReset = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int bytesSent = m_socket.SendTo(data, 0, numBytes, SocketFlags.None, target);
|
int bytesSent = m_socket.SendTo(data, 0, numBytes, SocketFlags.None, target);
|
||||||
if (numBytes != bytesSent)
|
if (numBytes != bytesSent)
|
||||||
LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!");
|
LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!");
|
||||||
}
|
}
|
||||||
|
catch (SocketException sx)
|
||||||
|
{
|
||||||
|
if (sx.SocketErrorCode == SocketError.ConnectionReset)
|
||||||
|
{
|
||||||
|
// connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
|
||||||
|
connectionReset = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LogError("Failed to send packet: " + sx);
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LogError("Failed to send packet: " + ex);
|
LogError("Failed to send packet: " + ex);
|
||||||
@@ -122,7 +137,7 @@ namespace Lidgren.Network
|
|||||||
//
|
//
|
||||||
// Release - just send the packet straight away
|
// Release - just send the packet straight away
|
||||||
//
|
//
|
||||||
internal void SendPacket(int numBytes, IPEndPoint target, int numMessages)
|
internal void SendPacket(int numBytes, IPEndPoint target, int numMessages, out bool connectionReset)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -130,6 +145,16 @@ namespace Lidgren.Network
|
|||||||
if (numBytes != bytesSent)
|
if (numBytes != bytesSent)
|
||||||
LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!");
|
LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!");
|
||||||
}
|
}
|
||||||
|
catch (SocketException sx)
|
||||||
|
{
|
||||||
|
if (sx.SocketErrorCode == SocketError.ConnectionReset)
|
||||||
|
{
|
||||||
|
// connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
|
||||||
|
connectionReset = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LogError("Failed to send packet: " + sx);
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LogError("Failed to send packet: " + ex);
|
LogError("Failed to send packet: " + ex);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Lidgren.Network
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class NetPeerConfiguration
|
public sealed class NetPeerConfiguration
|
||||||
{
|
{
|
||||||
private const string c_isLockedMessage = "You may not alter the NetPeerConfiguration after the NetPeer has been initialized!";
|
private const string c_isLockedMessage = "You may not modify the NetPeerConfiguration after it has been used to initialize a NetPeer";
|
||||||
|
|
||||||
private bool m_isLocked;
|
private bool m_isLocked;
|
||||||
internal bool m_acceptIncomingConnections;
|
internal bool m_acceptIncomingConnections;
|
||||||
|
|||||||
@@ -58,16 +58,16 @@ namespace UnitTests
|
|||||||
|
|
||||||
Console.WriteLine("Message encryption OK");
|
Console.WriteLine("Message encryption OK");
|
||||||
|
|
||||||
byte[] salt = NetUtility.ToByteArray("e6fb7e23f001f3e6c081"); // s
|
byte[] salt = NetUtility.ToByteArray("62191568b7a1aa18f8eb"); // s
|
||||||
byte[] verifier = NetSRP.ComputePasswordVerifier("user", "password", salt);
|
byte[] verifier = NetSRP.ComputePasswordVerifier("user", "password", salt);
|
||||||
|
|
||||||
Console.WriteLine("v = " + NetUtility.ToHexString(verifier));
|
Console.WriteLine("v = " + NetUtility.ToHexString(verifier));
|
||||||
|
|
||||||
byte[] a = NetUtility.ToByteArray("3b6485358d1721cb438cb7d0b3c5f8f46186d43e1c47db7cd8aa80e19760e409");
|
byte[] a = NetUtility.ToByteArray("129aac7ce0be45ab5f65ec0c6879222386c32177cb4024fe7ad593341c0a5085");
|
||||||
byte[] A = NetSRP.ComputeClientChallenge(a);
|
byte[] A = NetSRP.ComputeClientChallenge(a);
|
||||||
Console.WriteLine("A = " + NetUtility.ToHexString(A));
|
Console.WriteLine("A = " + NetUtility.ToHexString(A));
|
||||||
|
|
||||||
byte[] b = NetUtility.ToByteArray("fc17d424ce73a4c73e8fedfb25839e9917e861bc5253fff65697f81c75a87ea3");
|
byte[] b = NetUtility.ToByteArray("cdbe8cec49e33c78c0b434be67fa2fdb7646776e757bcf59fad51bbbee0d53a1");
|
||||||
Console.WriteLine("b = " + NetUtility.ToHexString(b));
|
Console.WriteLine("b = " + NetUtility.ToHexString(b));
|
||||||
byte[] B = NetSRP.ComputeServerChallenge(b, verifier);
|
byte[] B = NetSRP.ComputeServerChallenge(b, verifier);
|
||||||
Console.WriteLine("B = " + NetUtility.ToHexString(B));
|
Console.WriteLine("B = " + NetUtility.ToHexString(B));
|
||||||
|
|||||||
Reference in New Issue
Block a user