* Implements duplicate packet tracking. This virtually eliminates object duplication causing 2-3 duplicates depending on the UDP connection quality. This also eliminates duplicated chat, etc.
* It's verbose currently since this is new. You'll see: [CLIENT]: Warning Duplicate packet detected X Dropping. After this is sufficiently tested we'll remove that m_log.info line.0.6.0-stable
parent
5752c1f5c2
commit
715fbecd79
|
@ -47,6 +47,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
|
public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
|
||||||
|
|
||||||
|
public class PacketDupeLimiter
|
||||||
|
{
|
||||||
|
public PacketType pktype;
|
||||||
|
public int timeIn;
|
||||||
|
public uint packetId;
|
||||||
|
public PacketDupeLimiter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles new client connections
|
/// Handles new client connections
|
||||||
/// Constructor takes a single Packet and authenticates everything
|
/// Constructor takes a single Packet and authenticates everything
|
||||||
|
@ -83,6 +93,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
private int m_packetsSent = 0;
|
private int m_packetsSent = 0;
|
||||||
private int m_lastPacketsSentSentToScene = 0;
|
private int m_lastPacketsSentSentToScene = 0;
|
||||||
|
private int m_clearDuplicatePacketTrackingOlderThenXSeconds = 30;
|
||||||
|
|
||||||
private int m_probesWithNoIngressPackets = 0;
|
private int m_probesWithNoIngressPackets = 0;
|
||||||
private int m_lastPacketsReceived = 0;
|
private int m_lastPacketsReceived = 0;
|
||||||
|
@ -92,6 +103,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
private readonly uint m_circuitCode;
|
private readonly uint m_circuitCode;
|
||||||
private int m_moneyBalance;
|
private int m_moneyBalance;
|
||||||
|
|
||||||
|
private Dictionary<uint, PacketDupeLimiter> m_dupeLimiter = new Dictionary<uint, PacketDupeLimiter>();
|
||||||
|
|
||||||
private int m_animationSequenceNumber = 1;
|
private int m_animationSequenceNumber = 1;
|
||||||
|
|
||||||
private byte[] m_channelVersion = Helpers.StringToField("OpenSimulator 0.5"); // Dummy value needed by libSL
|
private byte[] m_channelVersion = Helpers.StringToField("OpenSimulator 0.5"); // Dummy value needed by libSL
|
||||||
|
@ -3837,6 +3850,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
m_lastPacketsSentSentToScene = m_packetsSent;
|
m_lastPacketsSentSentToScene = m_packetsSent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
protected void ClearOldPacketDupeTracking()
|
||||||
|
{
|
||||||
|
lock (m_dupeLimiter)
|
||||||
|
{
|
||||||
|
List<uint> toEliminate = new List<uint>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
foreach (uint seq in m_dupeLimiter.Keys)
|
||||||
|
{
|
||||||
|
PacketDupeLimiter pkdata = null;
|
||||||
|
m_dupeLimiter.TryGetValue(seq, out pkdata);
|
||||||
|
if (pkdata != null)
|
||||||
|
{
|
||||||
|
// doing a foreach loop, so we don't want to modify the dictionary while we're searching it
|
||||||
|
if (Util.UnixTimeSinceEpoch() - pkdata.timeIn > m_clearDuplicatePacketTrackingOlderThenXSeconds)
|
||||||
|
toEliminate.Add(seq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
m_log.Info("[PACKET]: Unable to clear dupe check packet data");
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the dupe packets that we detected in the loop above.
|
||||||
|
uint[] seqsToRemove = toEliminate.ToArray();
|
||||||
|
for (int i = 0; i<seqsToRemove.Length; i++)
|
||||||
|
{
|
||||||
|
if (m_dupeLimiter.ContainsKey(seqsToRemove[i]))
|
||||||
|
m_dupeLimiter.Remove(seqsToRemove[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -3866,7 +3913,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
protected void ProcessInPacket(Packet Pack)
|
protected void ProcessInPacket(Packet Pack)
|
||||||
{
|
{
|
||||||
ack_pack(Pack);
|
ack_pack(Pack);
|
||||||
|
lock (m_dupeLimiter)
|
||||||
|
{
|
||||||
|
if (m_dupeLimiter.ContainsKey(Pack.Header.Sequence))
|
||||||
|
{
|
||||||
|
m_log.Info("[CLIENT]: Warning Duplicate packet detected" + Pack.Type.ToString() + " Dropping.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PacketDupeLimiter pkdedupe = new PacketDupeLimiter();
|
||||||
|
pkdedupe.packetId = Pack.Header.ID;
|
||||||
|
pkdedupe.pktype = Pack.Type;
|
||||||
|
pkdedupe.timeIn = Util.UnixTimeSinceEpoch();
|
||||||
|
m_dupeLimiter.Add(Pack.Header.Sequence, pkdedupe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//m_log.Info("Sequence"
|
||||||
if (ProcessPacketMethod(Pack))
|
if (ProcessPacketMethod(Pack))
|
||||||
{
|
{
|
||||||
//there is a handler registered that handled this packet type
|
//there is a handler registered that handled this packet type
|
||||||
|
|
Loading…
Reference in New Issue