Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 32 additions & 19 deletions Lidgren.Network/NetPeer.LatencySimulation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
//#define USE_RELEASE_STATISTICS

using System;
using System.Buffers;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
Expand All @@ -36,9 +37,10 @@ public partial class NetPeer
private readonly List<DelayedPacket> m_delayedPackets = new List<DelayedPacket>();
private MWCRandom m_latencyRandom = new MWCRandom();

private sealed class DelayedPacket
private record struct DelayedPacket
{
public byte[] Data;
public int Length;
public double DelayedUntil;
public NetEndPoint Target;
}
Expand Down Expand Up @@ -84,13 +86,18 @@ internal void SendPacket(int numBytes, NetEndPoint target, int numMessages, out
for (int i = 0; i < num; i++)
{
delay = m + (m_latencyRandom.NextSingle() * r);
var data = GetStorage(numBytes);

Buffer.BlockCopy(m_sendBuffer, 0, data, 0, numBytes);

// Enqueue delayed packet
DelayedPacket p = new DelayedPacket();
p.Target = target;
p.Data = new byte[numBytes];
Buffer.BlockCopy(m_sendBuffer, 0, p.Data, 0, numBytes);
p.DelayedUntil = NetTime.Now + delay;
var p = new DelayedPacket
{
Target = target,
Data = data,
Length = numBytes,
DelayedUntil = NetTime.Now + delay
};

m_delayedPackets.Add(p);
}
Expand All @@ -110,18 +117,20 @@ private void SendDelayedPackets()
for (var i = 0; i < m_delayedPackets.Count; i++)
{
var p = m_delayedPackets[i];
if (now < p.DelayedUntil)
if (now < p.DelayedUntil)
continue;
ActuallySendPacket(p.Data, p.Data.Length, p.Target, out connectionReset);

ActuallySendPacket(p.Data, p.Length, p.Target, out connectionReset);

// Swap packet with last entry in list.
// This does not preserve order (we don't care) but is O(1).
var replaceIdx = m_delayedPackets.Count - 1;
var replacement = m_delayedPackets[replaceIdx];
m_delayedPackets[i] = replacement;
m_delayedPackets.RemoveAt(replaceIdx);


Recycle(p.Data);

// Make sure to decrement i so we re-process the element we just swapped in.
i -= 1;
}
Expand All @@ -133,7 +142,11 @@ private void FlushDelayedPackets()
{
bool connectionReset;
foreach (DelayedPacket p in m_delayedPackets)
ActuallySendPacket(p.Data, p.Data.Length, p.Target, out connectionReset);
{
ActuallySendPacket(p.Data, p.Length, p.Target, out connectionReset);
Recycle(p.Data);
}

m_delayedPackets.Clear();
}
catch { }
Expand All @@ -156,20 +169,20 @@ internal bool ActuallySendPacket(byte[] data, int numBytes, NetEndPoint target,
// TODO: refactor this check outta here
if (target.Address.Equals(ba))
{
// Some networks do not allow
// Some networks do not allow
// a global broadcast so we use the BroadcastAddress from the configuration
// this can be resolved to a local broadcast addresss e.g 192.168.x.255
// this can be resolved to a local broadcast addresss e.g 192.168.x.255
targetCopy.Address = m_configuration.BroadcastAddress;
targetCopy.Port = target.Port;
realTarget = targetCopy;
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);

if (dualStack)
{
NetUtility.CopyEndpoint(realTarget, targetCopy2); //Maps to IPv6 for Dual Mode
realTarget = targetCopy2;
}

}
else if (dualStack)
{
Expand All @@ -193,7 +206,7 @@ internal bool ActuallySendPacket(byte[] data, int numBytes, NetEndPoint target,
}
if (sx.SocketErrorCode == SocketError.ConnectionReset)
{
// connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
// connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
connectionReset = true;
return false;
}
Expand All @@ -215,15 +228,15 @@ internal bool SendMTUPacket(int numBytes, NetEndPoint target)
{
if (!CanAutoExpandMTU)
throw new NotSupportedException("MTU expansion not currently supported on this operating system");

try
{
// NOTE: Socket.DontFragment doesn't work on dual-stack sockets.
// The equivalent SetSocketOption does work.
// See: https://github.com/dotnet/runtime/issues/76410
if (m_socket.DualMode || target.AddressFamily == AddressFamily.InterNetwork)
m_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DontFragment, true);

int bytesSent = NetFastSocket.SendTo(m_socket, m_sendBuffer, 0, numBytes, SocketFlags.None, target);
if (numBytes != bytesSent)
LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!");
Expand Down
4 changes: 2 additions & 2 deletions Lidgren.Network/NetReliableSenderChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ internal override NetSendResult Enqueue(NetOutgoingMessage message)
return NetSendResult.Queued;
}

// call this regularely
// call this regularly
internal override void SendQueuedMessages(double now)
{
//
Expand Down Expand Up @@ -166,7 +166,7 @@ private void DestoreMessage(double now, int storeIndex, out bool resetTimeout)
#endif
// on each destore; reduce recyclingcount so that when all instances are destored, the outgoing message can be recycled
Interlocked.Decrement(ref storedMessage.m_recyclingCount);

if (storedMessage.m_recyclingCount <= 0)
m_connection.m_peer.Recycle(storedMessage);

Expand Down