Revamp packet handler to smooth out the stream of resent packets.
Eliminates the bursting in resends observed in the prior implementation0.6.1-post-fixes
parent
72ff5322f5
commit
35ec496f98
|
@ -54,7 +54,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
int PacketsReceived { get; }
|
int PacketsReceived { get; }
|
||||||
int PacketsReceivedReported { get; }
|
int PacketsReceivedReported { get; }
|
||||||
uint SilenceLimit { get; set; }
|
|
||||||
uint ResendTimeout { get; set; }
|
uint ResendTimeout { get; set; }
|
||||||
bool ReliableIsImportant { get; set; }
|
bool ReliableIsImportant { get; set; }
|
||||||
int MaxReliableResends { get; set; }
|
int MaxReliableResends { get; set; }
|
||||||
|
@ -124,7 +123,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of milliseconds that can pass before a packet that needs an ack is resent.
|
/// The number of milliseconds that can pass before a packet that needs an ack is resent.
|
||||||
/// </param>
|
/// </param>
|
||||||
private uint m_ResendTimeout = 2000;
|
private uint m_ResendTimeout = 4000;
|
||||||
|
|
||||||
public uint ResendTimeout
|
public uint ResendTimeout
|
||||||
{
|
{
|
||||||
|
@ -132,14 +131,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
set { m_ResendTimeout = value; }
|
set { m_ResendTimeout = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint m_SilenceLimit = 250;
|
|
||||||
|
|
||||||
public uint SilenceLimit
|
|
||||||
{
|
|
||||||
get { return m_SilenceLimit; }
|
|
||||||
set { m_SilenceLimit = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private int m_MaxReliableResends = 3;
|
private int m_MaxReliableResends = 3;
|
||||||
|
|
||||||
public int MaxReliableResends
|
public int MaxReliableResends
|
||||||
|
@ -148,8 +139,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
set { m_MaxReliableResends = value; }
|
set { m_MaxReliableResends = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private int m_LastAck = 0;
|
|
||||||
|
|
||||||
// Track duplicated packets. This uses a Dictionary. Both insertion
|
// Track duplicated packets. This uses a Dictionary. Both insertion
|
||||||
// and lookup are common operations and need to take advantage of
|
// and lookup are common operations and need to take advantage of
|
||||||
// the hashing. Expiration is less common and can be allowed the
|
// the hashing. Expiration is less common and can be allowed the
|
||||||
|
@ -168,6 +157,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
private int m_PacketsSentReported = 0;
|
private int m_PacketsSentReported = 0;
|
||||||
private int m_UnackedBytes = 0;
|
private int m_UnackedBytes = 0;
|
||||||
|
|
||||||
|
private int m_LastResend = 0;
|
||||||
|
|
||||||
public int PacketsReceived
|
public int PacketsReceived
|
||||||
{
|
{
|
||||||
get { return m_PacketsReceived; }
|
get { return m_PacketsReceived; }
|
||||||
|
@ -211,6 +202,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
set { m_ReliableIsImportant = value; }
|
set { m_ReliableIsImportant = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int m_DropSafeTimeout;
|
||||||
|
|
||||||
LLPacketServer m_PacketServer;
|
LLPacketServer m_PacketServer;
|
||||||
private byte[] m_ZeroOutBuffer = new byte[4096];
|
private byte[] m_ZeroOutBuffer = new byte[4096];
|
||||||
|
|
||||||
|
@ -222,6 +215,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
m_Client = client;
|
m_Client = client;
|
||||||
m_PacketServer = server;
|
m_PacketServer = server;
|
||||||
|
m_DropSafeTimeout = System.Environment.TickCount + 15000;
|
||||||
|
|
||||||
m_PacketQueue = new LLPacketQueue(client.AgentId, userSettings);
|
m_PacketQueue = new LLPacketQueue(client.AgentId, userSettings);
|
||||||
|
|
||||||
|
@ -235,6 +229,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
m_PacketQueue.Enqueue(null);
|
m_PacketQueue.Enqueue(null);
|
||||||
m_PacketQueue.Close();
|
m_PacketQueue.Close();
|
||||||
|
m_Client = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send one packet. This actually doesn't send anything, it queues
|
// Send one packet. This actually doesn't send anything, it queues
|
||||||
|
@ -327,15 +322,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
private void ResendUnacked()
|
private void ResendUnacked()
|
||||||
{
|
{
|
||||||
int now = System.Environment.TickCount;
|
int now = System.Environment.TickCount;
|
||||||
int lastAck = m_LastAck;
|
|
||||||
|
int intervalMs = 250;
|
||||||
|
|
||||||
|
if (m_LastResend != 0)
|
||||||
|
intervalMs = now - m_LastResend;
|
||||||
|
|
||||||
|
lock (m_NeedAck)
|
||||||
|
{
|
||||||
|
if (m_DropSafeTimeout > now ||
|
||||||
|
intervalMs > 500) // We were frozen!
|
||||||
|
{
|
||||||
|
foreach (AckData data in new List<AckData>
|
||||||
|
(m_NeedAck.Values))
|
||||||
|
{
|
||||||
|
if (m_DropSafeTimeout > now)
|
||||||
|
{
|
||||||
|
m_NeedAck[data.Packet.Header.Sequence].
|
||||||
|
TickCount = now;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_NeedAck[data.Packet.Header.Sequence].
|
||||||
|
TickCount += intervalMs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_LastResend = now;
|
||||||
|
|
||||||
// Unless we have received at least one ack, don't bother resending
|
// Unless we have received at least one ack, don't bother resending
|
||||||
// anything. There may not be a client there, don't clog up the
|
// anything. There may not be a client there, don't clog up the
|
||||||
// pipes.
|
// pipes.
|
||||||
//
|
//
|
||||||
if (lastAck == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
lock (m_NeedAck)
|
lock (m_NeedAck)
|
||||||
{
|
{
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
|
@ -343,16 +362,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (m_NeedAck.Count == 0)
|
if (m_NeedAck.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If we have seen no acks in <SilenceLimit> s but are
|
int resent = 0;
|
||||||
// waiting for acks, then there may be no one listening.
|
|
||||||
// No need to resend anything. Keep it until it gets stale,
|
|
||||||
// then it will be dropped.
|
|
||||||
//
|
|
||||||
if ((((now - lastAck) > m_SilenceLimit) &&
|
|
||||||
m_NeedAck.Count > 0) || m_NeedAck.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (AckData data in new List<AckData>(m_NeedAck.Values))
|
foreach (AckData data in new List<AckData>(m_NeedAck.Values))
|
||||||
{
|
{
|
||||||
|
@ -362,25 +372,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
//
|
//
|
||||||
if ((now - data.TickCount) > m_ResendTimeout)
|
if ((now - data.TickCount) > m_ResendTimeout)
|
||||||
{
|
{
|
||||||
m_NeedAck[packet.Header.Sequence].Resends++;
|
if (resent < 20)
|
||||||
|
|
||||||
// The client needs to be told that a packet is being resent, otherwise it appears to believe
|
|
||||||
// that it should reset its sequence to that packet number.
|
|
||||||
packet.Header.Resent = true;
|
|
||||||
|
|
||||||
if (m_NeedAck[packet.Header.Sequence].Resends >=
|
|
||||||
m_MaxReliableResends && (!m_ReliableIsImportant))
|
|
||||||
{
|
{
|
||||||
m_NeedAck.Remove(packet.Header.Sequence);
|
m_NeedAck[packet.Header.Sequence].Resends++;
|
||||||
TriggerOnPacketDrop(packet, data.Identifier);
|
|
||||||
continue;
|
// The client needs to be told that a packet is being resent, otherwise it appears to believe
|
||||||
|
// that it should reset its sequence to that packet number.
|
||||||
|
packet.Header.Resent = true;
|
||||||
|
|
||||||
|
if ((m_NeedAck[packet.Header.Sequence].Resends >=
|
||||||
|
m_MaxReliableResends) && (!m_ReliableIsImportant))
|
||||||
|
{
|
||||||
|
m_NeedAck.Remove(packet.Header.Sequence);
|
||||||
|
TriggerOnPacketDrop(packet, data.Identifier);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_NeedAck[packet.Header.Sequence].TickCount =
|
||||||
|
System.Environment.TickCount;
|
||||||
|
|
||||||
|
QueuePacket(packet, ThrottleOutPacketType.Resend,
|
||||||
|
data.Identifier);
|
||||||
|
|
||||||
|
resent++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_NeedAck[packet.Header.Sequence].TickCount +=
|
||||||
|
intervalMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_NeedAck[packet.Header.Sequence].TickCount =
|
|
||||||
System.Environment.TickCount;
|
|
||||||
|
|
||||||
QueuePacket(packet, ThrottleOutPacketType.Resend,
|
|
||||||
data.Identifier);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -623,8 +643,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
m_NeedAck.Remove(id);
|
m_NeedAck.Remove(id);
|
||||||
m_UnackedBytes -= packet.ToBytes().Length;
|
m_UnackedBytes -= packet.ToBytes().Length;
|
||||||
|
|
||||||
m_LastAck = System.Environment.TickCount;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue