1
0
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:
lidgren
2010-06-09 06:12:06 +00:00
parent 4e3aa68195
commit caf68daab7
8 changed files with 158 additions and 24 deletions

View File

@@ -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;
}
}
}
}

View File

@@ -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";
}
}

View File

@@ -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)

View File

@@ -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]",

View File

@@ -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");
}
}
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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));