You've already forked lidgren-network-gen3
mirror of
https://github.com/lidgren/lidgren-network-gen3.git
synced 2026-05-15 22:56:30 +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)
|
||||
{
|
||||
// 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);
|
||||
numIncludedMessages = 0;
|
||||
m_throttleDebt += ptr;
|
||||
@@ -247,10 +256,19 @@ namespace Lidgren.Network
|
||||
|
||||
if (ptr > 0)
|
||||
{
|
||||
m_owner.SendPacket(ptr, m_remoteEndpoint, numIncludedMessages);
|
||||
m_statistics.PacketSent(ptr, numIncludedMessages);
|
||||
numIncludedMessages = 0;
|
||||
m_throttleDebt += ptr;
|
||||
bool connectionReset;
|
||||
m_owner.SendPacket(ptr, m_remoteEndpoint, numIncludedMessages, out connectionReset);
|
||||
if (connectionReset)
|
||||
{
|
||||
// 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
|
||||
/// </summary>
|
||||
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 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);
|
||||
|
||||
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)
|
||||
function srp_compute_client_S(BB, xx, uu, aa, kk) {
|
||||
@@ -243,7 +302,7 @@ function srp_compute_client_S(BB, xx, uu, aa, kk) {
|
||||
return btmp.modPow(xx.multiply(uu).add(aa), N);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public static byte[] ComputeServerToken(byte[] clientChallenge, byte[] verifier, byte[] u, byte[] serverChallengeSalt)
|
||||
{
|
||||
// S = (Av^u) ^ b (mod N)
|
||||
|
||||
@@ -130,6 +130,28 @@ namespace Lidgren.Network
|
||||
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()
|
||||
{
|
||||
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);
|
||||
bool connectionReset = false;
|
||||
|
||||
if (recipient.Address.Equals(IPAddress.Broadcast))
|
||||
{
|
||||
@@ -237,7 +238,7 @@ namespace Lidgren.Network
|
||||
try
|
||||
{
|
||||
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
|
||||
SendPacket(ptr, recipient, 1);
|
||||
SendPacket(ptr, recipient, 1, out connectionReset);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -247,8 +248,11 @@ namespace Lidgren.Network
|
||||
else
|
||||
{
|
||||
// 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
|
||||
@@ -276,9 +280,9 @@ namespace Lidgren.Network
|
||||
catch (SocketException sx)
|
||||
{
|
||||
// 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?!
|
||||
//LogWarning("Connection reset by peer, seemingly from " + m_senderRemote);
|
||||
return;
|
||||
@@ -288,7 +292,7 @@ namespace Lidgren.Network
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytesReceived < 1)
|
||||
if (bytesReceived < NetPeer.kMinPacketHeaderSize)
|
||||
return;
|
||||
|
||||
// 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);
|
||||
Interlocked.Decrement(ref msg.m_inQueueCount);
|
||||
|
||||
SendPacket(len, conn.m_remoteEndpoint, 1);
|
||||
bool connectionReset;
|
||||
SendPacket(len, conn.m_remoteEndpoint, 1, out connectionReset);
|
||||
|
||||
Recycle(msg);
|
||||
|
||||
if (connectionReset)
|
||||
LogWarning("Connection was reset; remote host is not listening");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,8 +37,10 @@ namespace Lidgren.Network
|
||||
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
|
||||
float loss = m_configuration.m_loss;
|
||||
if (loss > 0.0f)
|
||||
@@ -59,7 +61,7 @@ namespace Lidgren.Network
|
||||
{
|
||||
// no latency simulation
|
||||
//LogVerbose("Sending packet " + numBytes + " bytes");
|
||||
ActuallySendPacket(m_sendBuffer, numBytes, target);
|
||||
ActuallySendPacket(m_sendBuffer, numBytes, target, out connectionReset);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -92,26 +94,39 @@ namespace Lidgren.Network
|
||||
|
||||
double now = NetTime.Now;
|
||||
|
||||
bool connectionReset;
|
||||
|
||||
RestartDelaySending:
|
||||
foreach (DelayedPacket p in m_delayedPackets)
|
||||
{
|
||||
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);
|
||||
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
|
||||
{
|
||||
int bytesSent = m_socket.SendTo(data, 0, numBytes, SocketFlags.None, target);
|
||||
if (numBytes != bytesSent)
|
||||
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)
|
||||
{
|
||||
LogError("Failed to send packet: " + ex);
|
||||
@@ -122,7 +137,7 @@ namespace Lidgren.Network
|
||||
//
|
||||
// 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
|
||||
{
|
||||
@@ -130,6 +145,16 @@ namespace Lidgren.Network
|
||||
if (numBytes != bytesSent)
|
||||
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)
|
||||
{
|
||||
LogError("Failed to send packet: " + ex);
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Lidgren.Network
|
||||
/// </summary>
|
||||
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;
|
||||
internal bool m_acceptIncomingConnections;
|
||||
|
||||
@@ -58,16 +58,16 @@ namespace UnitTests
|
||||
|
||||
Console.WriteLine("Message encryption OK");
|
||||
|
||||
byte[] salt = NetUtility.ToByteArray("e6fb7e23f001f3e6c081"); // s
|
||||
byte[] salt = NetUtility.ToByteArray("62191568b7a1aa18f8eb"); // s
|
||||
byte[] verifier = NetSRP.ComputePasswordVerifier("user", "password", salt);
|
||||
|
||||
Console.WriteLine("v = " + NetUtility.ToHexString(verifier));
|
||||
|
||||
byte[] a = NetUtility.ToByteArray("3b6485358d1721cb438cb7d0b3c5f8f46186d43e1c47db7cd8aa80e19760e409");
|
||||
byte[] a = NetUtility.ToByteArray("129aac7ce0be45ab5f65ec0c6879222386c32177cb4024fe7ad593341c0a5085");
|
||||
byte[] A = NetSRP.ComputeClientChallenge(a);
|
||||
Console.WriteLine("A = " + NetUtility.ToHexString(A));
|
||||
|
||||
byte[] b = NetUtility.ToByteArray("fc17d424ce73a4c73e8fedfb25839e9917e861bc5253fff65697f81c75a87ea3");
|
||||
byte[] b = NetUtility.ToByteArray("cdbe8cec49e33c78c0b434be67fa2fdb7646776e757bcf59fad51bbbee0d53a1");
|
||||
Console.WriteLine("b = " + NetUtility.ToHexString(b));
|
||||
byte[] B = NetSRP.ComputeServerChallenge(b, verifier);
|
||||
Console.WriteLine("B = " + NetUtility.ToHexString(B));
|
||||
|
||||
Reference in New Issue
Block a user