changes on lludp acks and resends
parent
7516288634
commit
066a6fbaa1
|
@ -4482,7 +4482,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
Utils.FloatToBytesSafepos(hover, data, pos); pos += 4;
|
||||
|
||||
buf.DataLength = pos;
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true);
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, true);
|
||||
}
|
||||
|
||||
static private readonly byte[] AvatarAnimationHeader = new byte[] {
|
||||
|
@ -4638,7 +4638,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
CreateImprovedTerseBlock(ent, buf.Data, ref pos, false);
|
||||
|
||||
buf.DataLength = pos;
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true);
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, true);
|
||||
}
|
||||
|
||||
//UUID m_courseLocationPrey = UUID.Zero;
|
||||
|
@ -5197,7 +5197,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
||||
//delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
|
||||
null, false, false);
|
||||
null, false);
|
||||
|
||||
buf = newbuf;
|
||||
zc.Data = buf.Data;
|
||||
|
@ -5221,7 +5221,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
buf.DataLength = zc.Finish();
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
||||
//delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
|
||||
null, false, false);
|
||||
null, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5359,7 +5359,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
||||
//delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
|
||||
null, false, false);
|
||||
null, false);
|
||||
|
||||
buf = newbuf;
|
||||
zc.Data = buf.Data;
|
||||
|
@ -5383,7 +5383,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
buf.DataLength = zc.Finish();
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
||||
//delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
|
||||
null, false, false);
|
||||
null, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5432,7 +5432,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
buf.Data[countposition] = (byte)count;
|
||||
buf.DataLength = pos;
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, false);
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false);
|
||||
|
||||
buf = newbuf;
|
||||
data = buf.Data;
|
||||
|
@ -5446,7 +5446,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
buf.Data[countposition] = (byte)count;
|
||||
buf.DataLength = pos;
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, false);
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5493,8 +5493,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
buf.DataLength = lastpos;
|
||||
// zero encode is not as spec
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
||||
//delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
|
||||
null, false, true);
|
||||
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, true);
|
||||
//null, false, true);
|
||||
|
||||
tau = new List<EntityUpdate>(30);
|
||||
tau.Add(eu);
|
||||
|
@ -5509,8 +5509,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
buf.Data[17] = (byte)count;
|
||||
buf.DataLength = pos;
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
||||
//delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true);
|
||||
null, false, true);
|
||||
//delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, true);
|
||||
null, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14541,7 +14541,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length);
|
||||
#endregion BinaryStats
|
||||
|
||||
OutPacket(packet, throttlePacketType, true);
|
||||
OutPacket(packet, throttlePacketType, true, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -15174,7 +15174,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
int pos = 18;
|
||||
CreateImprovedTerseBlock(p, buf.Data, ref pos, false);
|
||||
buf.DataLength = pos;
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true);
|
||||
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <summary>Circuit code that this client is connected on</summary>
|
||||
public readonly uint CircuitCode;
|
||||
/// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
|
||||
public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(256);
|
||||
public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(1024);
|
||||
|
||||
/// <summary>Packets we have sent that need to be ACKed by the client</summary>
|
||||
public UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
|
||||
|
@ -123,6 +123,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
|
||||
public DoubleLocklessQueue<uint> PendingAcks = new DoubleLocklessQueue<uint>();
|
||||
|
||||
public int AckStalls;
|
||||
|
||||
/// <summary>Current packet sequence number</summary>
|
||||
public int CurrentSequence;
|
||||
/// <summary>Current ping sequence number</summary>
|
||||
|
@ -185,7 +187,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
private byte[] m_packedThrottles;
|
||||
|
||||
private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
|
||||
private int m_maxRTO = 10000;
|
||||
private int m_maxRTO = 3000;
|
||||
private int m_minRTO = 250;
|
||||
public bool m_deliverPackets = true;
|
||||
|
||||
private float m_burstTime;
|
||||
|
@ -538,47 +541,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
/// true if the packet has been queued,
|
||||
/// false if the packet has not been queued and should be sent immediately.
|
||||
/// </returns>
|
||||
public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue)
|
||||
public bool EnqueueOutgoing(OutgoingPacket packet)
|
||||
{
|
||||
return EnqueueOutgoing(packet, forceQueue, false);
|
||||
return EnqueueOutgoing(packet, false);
|
||||
}
|
||||
|
||||
public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue, bool highPriority)
|
||||
public bool EnqueueOutgoing(OutgoingPacket packet, bool highPriority)
|
||||
{
|
||||
int category = (int)packet.Category;
|
||||
|
||||
if (category >= 0 && category < m_packetOutboxes.Length)
|
||||
{
|
||||
DoubleLocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
|
||||
|
||||
if (forceQueue || m_deliverPackets == false)
|
||||
{
|
||||
queue.Enqueue(packet, highPriority);
|
||||
return true;
|
||||
}
|
||||
|
||||
// need to enqueue if queue is not empty
|
||||
if (queue.Count > 0 || m_nextPackets[category] != null)
|
||||
{
|
||||
queue.Enqueue(packet, highPriority);
|
||||
return true;
|
||||
}
|
||||
|
||||
// check bandwidth
|
||||
TokenBucket bucket = m_throttleCategories[category];
|
||||
if (bucket.CheckTokens(packet.Buffer.DataLength))
|
||||
{
|
||||
// enough tokens so it can be sent imediatly by caller
|
||||
bucket.RemoveTokens(packet.Buffer.DataLength);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Force queue specified or not enough tokens in the bucket, queue this packet
|
||||
queue.Enqueue(packet, highPriority);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't have a token bucket for this category, so it will not be queued
|
||||
|
@ -608,33 +585,84 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
OutgoingPacket packet = null;
|
||||
DoubleLocklessQueue<OutgoingPacket> queue;
|
||||
TokenBucket bucket;
|
||||
bool packetSent = false;
|
||||
ThrottleOutPacketTypeFlags emptyCategories = 0;
|
||||
|
||||
//string queueDebugOutput = String.Empty; // Serious debug business
|
||||
// do resends
|
||||
|
||||
for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
|
||||
packet = m_nextPackets[0];
|
||||
if (packet != null)
|
||||
{
|
||||
if (packet.Buffer != null)
|
||||
{
|
||||
if (m_throttleCategories[0].RemoveTokens(packet.Buffer.DataLength))
|
||||
{
|
||||
// Send the packet
|
||||
m_udpServer.SendPacketFinal(packet);
|
||||
packetSent = true;
|
||||
m_nextPackets[0] = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_nextPackets[0] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
queue = m_packetOutboxes[0];
|
||||
if (queue != null)
|
||||
{
|
||||
if(queue.Dequeue(out packet))
|
||||
{
|
||||
// A packet was pulled off the queue. See if we have
|
||||
// enough tokens in the bucket to send it out
|
||||
if (packet.Buffer != null)
|
||||
{
|
||||
if (m_throttleCategories[0].RemoveTokens(packet.Buffer.DataLength))
|
||||
{
|
||||
// Send the packet
|
||||
m_udpServer.SendPacketFinal(packet);
|
||||
packetSent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save the dequeued packet for the next iteration
|
||||
m_nextPackets[0] = packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_packetOutboxes[0] = new DoubleLocklessQueue<OutgoingPacket>();
|
||||
}
|
||||
}
|
||||
|
||||
if(NeedAcks.Count() > 50)
|
||||
{
|
||||
Interlocked.Increment(ref AckStalls);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 1; i < THROTTLE_CATEGORY_COUNT; i++)
|
||||
{
|
||||
bucket = m_throttleCategories[i];
|
||||
//queueDebugOutput += m_packetOutboxes[i].Count + " "; // Serious debug business
|
||||
|
||||
if (m_nextPackets[i] != null)
|
||||
packet = m_nextPackets[i];
|
||||
if (packet != null)
|
||||
{
|
||||
// This bucket was empty the last time we tried to send a packet,
|
||||
// leaving a dequeued packet still waiting to be sent out. Try to
|
||||
// send it again
|
||||
OutgoingPacket nextPacket = m_nextPackets[i];
|
||||
if(nextPacket.Buffer == null)
|
||||
if(packet.Buffer == null)
|
||||
{
|
||||
if (m_packetOutboxes[i].Count < 5)
|
||||
emptyCategories |= CategoryToFlag(i);
|
||||
m_nextPackets[i] = null;
|
||||
continue;
|
||||
}
|
||||
if (bucket.RemoveTokens(nextPacket.Buffer.DataLength))
|
||||
|
||||
if (m_throttleCategories[i].RemoveTokens(packet.Buffer.DataLength))
|
||||
{
|
||||
// Send the packet
|
||||
m_udpServer.SendPacketFinal(nextPacket);
|
||||
m_udpServer.SendPacketFinal(packet);
|
||||
m_nextPackets[i] = null;
|
||||
packetSent = true;
|
||||
|
||||
|
@ -647,35 +675,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
// No dequeued packet waiting to be sent, try to pull one off
|
||||
// this queue
|
||||
queue = m_packetOutboxes[i];
|
||||
if (queue != null)
|
||||
if(queue.Dequeue(out packet))
|
||||
{
|
||||
bool success = false;
|
||||
try
|
||||
{
|
||||
success = queue.Dequeue(out packet);
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
// A packet was pulled off the queue. See if we have
|
||||
// enough tokens in the bucket to send it out
|
||||
if (packet.Buffer == null)
|
||||
{
|
||||
// packet canceled elsewhere (by a ack for example)
|
||||
if (queue.Count < 5)
|
||||
emptyCategories |= CategoryToFlag(i);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bucket.RemoveTokens(packet.Buffer.DataLength))
|
||||
|
||||
if (m_throttleCategories[i].RemoveTokens(packet.Buffer.DataLength))
|
||||
{
|
||||
// Send the packet
|
||||
m_udpServer.SendPacketFinal(packet);
|
||||
packetSent = true;
|
||||
|
||||
if (queue.Count < 5)
|
||||
emptyCategories |= CategoryToFlag(i);
|
||||
}
|
||||
|
@ -685,7 +699,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
m_nextPackets[i] = packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No packets in this queue. Fire the queue empty callback
|
||||
|
@ -693,12 +706,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
emptyCategories |= CategoryToFlag(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
|
||||
emptyCategories |= CategoryToFlag(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (emptyCategories != 0)
|
||||
|
@ -718,8 +725,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
p *= 5;
|
||||
if( p> m_maxRTO)
|
||||
p = m_maxRTO;
|
||||
else if(p < m_defaultRTO)
|
||||
p = m_defaultRTO;
|
||||
else if(p < m_minRTO)
|
||||
p = m_minRTO;
|
||||
|
||||
m_RTO = p;
|
||||
}
|
||||
|
|
|
@ -880,8 +880,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
// If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
|
||||
// continue to display the deleted object until relog. Therefore, we need to always queue a kill object
|
||||
// packet so that it isn't sent before a queued update packet.
|
||||
bool requestQueue = type == PacketType.KillObject;
|
||||
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority))
|
||||
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, highPriority))
|
||||
{
|
||||
SendPacketFinal(outgoingPacket);
|
||||
return true;
|
||||
|
@ -952,7 +951,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
|
||||
public void SendUDPPacket(
|
||||
LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue, bool zerocode)
|
||||
LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool zerocode)
|
||||
{
|
||||
bool highPriority = false;
|
||||
|
||||
|
@ -971,7 +970,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0)
|
||||
outgoingPacket.UnackedMethod = ((method == null) ? delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
|
||||
|
||||
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forcequeue, highPriority))
|
||||
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, highPriority))
|
||||
SendPacketFinal(outgoingPacket);
|
||||
}
|
||||
|
||||
|
@ -991,7 +990,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0)
|
||||
outgoingPacket.UnackedMethod = delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); };
|
||||
|
||||
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false, highPriority))
|
||||
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, highPriority))
|
||||
SendPacketFinal(outgoingPacket);
|
||||
}
|
||||
|
||||
|
@ -1056,11 +1055,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
data[7] = udpClient.CurrentPingSequence++;
|
||||
// older seq number of our un ack packets, so viewers could clean deduplication lists TODO
|
||||
//Utils.UIntToBytes(0, data, 8);
|
||||
data[8] = 0;
|
||||
data[9] = 0;
|
||||
data[10] = 0;
|
||||
data[11] = 0;
|
||||
Utils.UIntToBytes(udpClient.NeedAcks.Oldest(), data, 8);
|
||||
|
||||
buf.DataLength = 12;
|
||||
SendUDPPacket(udpClient, buf, ThrottleOutPacketType.Unknown);
|
||||
|
@ -1140,7 +1135,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
// Bump up the resend count on this packet
|
||||
Interlocked.Increment(ref outgoingPacket.ResendCount);
|
||||
|
||||
// Requeue or resend the packet
|
||||
if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false))
|
||||
SendPacketFinal(outgoingPacket);
|
||||
|
@ -1162,7 +1156,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
return;
|
||||
LLUDPClient udpClient = outgoingPacket.Client;
|
||||
if (!udpClient.IsConnected)
|
||||
{
|
||||
FreeUDPBuffer(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
byte flags = buffer.Data[0];
|
||||
bool isResend = (flags & Helpers.MSG_RESENT) != 0;
|
||||
|
@ -1172,7 +1169,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
int dataLength = buffer.DataLength;
|
||||
|
||||
// only append acks on plain reliable messages
|
||||
if (flags == Helpers.MSG_RELIABLE)
|
||||
if (flags == Helpers.MSG_RELIABLE && outgoingPacket.UnackedMethod == null)
|
||||
{
|
||||
// Keep appending ACKs until there is no room left in the buffer or there are
|
||||
// no more ACKs to append
|
||||
|
@ -1211,10 +1208,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
// Stats tracking
|
||||
Interlocked.Increment(ref udpClient.PacketsSent);
|
||||
PacketsSentCount++;
|
||||
|
||||
SyncSend(buffer);
|
||||
|
||||
// Keep track of when this packet was sent out (right now)
|
||||
outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
|
||||
int enow = Environment.TickCount & Int32.MaxValue;
|
||||
Interlocked.Exchange(ref outgoingPacket.TickCount, enow);
|
||||
|
||||
if (outgoingPacket.UnackedMethod == null)
|
||||
FreeUDPBuffer(buffer);
|
||||
|
@ -1935,7 +1934,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
m_resendUnacked = true;
|
||||
m_elapsedMSOutgoingPacketHandler = 0.0;
|
||||
m_elapsed100MSOutgoingPacketHandler += 1;
|
||||
++m_elapsed100MSOutgoingPacketHandler;
|
||||
}
|
||||
|
||||
// Check for pending outgoing ACKs every 500ms
|
||||
|
@ -1943,7 +1942,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
m_sendAcks = true;
|
||||
m_elapsed100MSOutgoingPacketHandler = 0;
|
||||
m_elapsed500MSOutgoingPacketHandler += 1;
|
||||
++m_elapsed500MSOutgoingPacketHandler;
|
||||
}
|
||||
|
||||
// Send pings to clients every 5000ms
|
||||
|
|
|
@ -66,21 +66,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
//private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>Holds the actual unacked packet data, sorted by sequence number</summary>
|
||||
private Dictionary<uint, OutgoingPacket> m_packets = new Dictionary<uint, OutgoingPacket>();
|
||||
private SortedDictionary<uint, OutgoingPacket> m_packets = new SortedDictionary<uint, OutgoingPacket>();
|
||||
/// <summary>Holds packets that need to be added to the unacknowledged list</summary>
|
||||
private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>();
|
||||
/// <summary>Holds information about pending acknowledgements</summary>
|
||||
private LocklessQueue<PendingAck> m_pendingAcknowledgements = new LocklessQueue<PendingAck>();
|
||||
/// <summary>Holds information about pending removals</summary>
|
||||
private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>();
|
||||
|
||||
|
||||
private uint m_older;
|
||||
public void Clear()
|
||||
{
|
||||
m_packets.Clear();
|
||||
m_pendingAdds = null;
|
||||
m_pendingAcknowledgements = null;
|
||||
m_pendingRemoves = null;
|
||||
m_older = 0;
|
||||
}
|
||||
|
||||
public int Count()
|
||||
{
|
||||
return m_packets.Count + m_pendingAdds.Count - m_pendingAcknowledgements.Count - m_pendingRemoves.Count;
|
||||
}
|
||||
|
||||
public uint Oldest()
|
||||
{
|
||||
return m_older;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -148,27 +158,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
ProcessQueues();
|
||||
|
||||
List<OutgoingPacket> expiredPackets = null;
|
||||
|
||||
bool doolder = true;
|
||||
if (m_packets.Count > 0)
|
||||
{
|
||||
int now = Environment.TickCount & Int32.MaxValue;
|
||||
|
||||
foreach (OutgoingPacket packet in m_packets.Values)
|
||||
{
|
||||
if(packet.Buffer == null)
|
||||
{
|
||||
Remove(packet.SequenceNumber);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(doolder)
|
||||
{
|
||||
m_older = packet.SequenceNumber;
|
||||
doolder = false;
|
||||
}
|
||||
|
||||
// TickCount of zero means a packet is in the resend queue
|
||||
// but hasn't actually been sent over the wire yet
|
||||
if (packet.TickCount == 0)
|
||||
int ptime = Interlocked.Exchange(ref packet.TickCount, 0);
|
||||
if (ptime == 0)
|
||||
continue;
|
||||
|
||||
if (now - packet.TickCount >= timeoutMS)
|
||||
if(now - ptime < timeoutMS)
|
||||
{
|
||||
int t = Interlocked.Exchange(ref packet.TickCount, ptime);
|
||||
if (t > ptime)
|
||||
Interlocked.Exchange(ref packet.TickCount, t);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (expiredPackets == null)
|
||||
expiredPackets = new List<OutgoingPacket>();
|
||||
|
||||
// The TickCount will be set to the current time when the packet
|
||||
// is actually sent out again
|
||||
packet.TickCount = 0;
|
||||
|
||||
// As with other network applications, assume that an expired packet is
|
||||
// an indication of some network problem, slow transmission
|
||||
packet.Client.FlowThrottle.ExpirePackets(1);
|
||||
|
@ -176,7 +201,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
expiredPackets.Add(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (expiredPackets != null)
|
||||
// m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Found {0} expired packets on timeout of {1}", expiredPackets.Count, timeoutMS);
|
||||
|
@ -186,59 +210,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
private void ProcessQueues()
|
||||
{
|
||||
// Process all the pending adds
|
||||
OutgoingPacket pendingAdd;
|
||||
while (m_pendingAdds.TryDequeue(out pendingAdd))
|
||||
while (m_pendingRemoves.TryDequeue(out uint pendingRemove))
|
||||
{
|
||||
if (pendingAdd != null)
|
||||
m_packets[pendingAdd.SequenceNumber] = pendingAdd;
|
||||
}
|
||||
|
||||
// Process all the pending removes, including updating statistics and round-trip times
|
||||
PendingAck pendingAcknowledgement;
|
||||
while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
|
||||
{
|
||||
//m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Processing ack {0}", pendingAcknowledgement.SequenceNumber);
|
||||
OutgoingPacket ackedPacket;
|
||||
if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
|
||||
{
|
||||
if (ackedPacket != null)
|
||||
{
|
||||
m_packets.Remove(pendingAcknowledgement.SequenceNumber);
|
||||
|
||||
// Update stats
|
||||
Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
|
||||
|
||||
ackedPacket.Client.FreeUDPBuffer(ackedPacket.Buffer);
|
||||
ackedPacket.Buffer = null;
|
||||
|
||||
// As with other network applications, assume that an acknowledged packet is an
|
||||
// indication that the network can handle a little more load, speed up the transmission
|
||||
ackedPacket.Client.FlowThrottle.AcknowledgePackets(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_log.WarnFormat("[UNACKED PACKET COLLECTION]: found null packet for sequence number {0} to ack",
|
||||
// pendingAcknowledgement.SequenceNumber);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_log.WarnFormat("[UNACKED PACKET COLLECTION]: Could not find packet with sequence number {0} to ack",
|
||||
// pendingAcknowledgement.SequenceNumber);
|
||||
}
|
||||
}
|
||||
|
||||
uint pendingRemove;
|
||||
while(m_pendingRemoves.TryDequeue(out pendingRemove))
|
||||
{
|
||||
OutgoingPacket removedPacket;
|
||||
if (m_packets.TryGetValue(pendingRemove, out removedPacket))
|
||||
{
|
||||
if (removedPacket != null)
|
||||
if (m_packets.TryGetValue(pendingRemove, out OutgoingPacket removedPacket))
|
||||
{
|
||||
m_packets.Remove(pendingRemove);
|
||||
|
||||
if (removedPacket != null)
|
||||
{
|
||||
// Update stats
|
||||
Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
|
||||
|
||||
|
@ -247,6 +225,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process all the pending adds
|
||||
while (m_pendingAdds.TryDequeue(out OutgoingPacket pendingAdd))
|
||||
{
|
||||
if (pendingAdd != null)
|
||||
m_packets[pendingAdd.SequenceNumber] = pendingAdd;
|
||||
}
|
||||
|
||||
// Process all the pending removes, including updating statistics and round-trip times
|
||||
while (m_pendingAcknowledgements.TryDequeue(out PendingAck pendingAcknowledgement))
|
||||
{
|
||||
//m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Processing ack {0}", pendingAcknowledgement.SequenceNumber);
|
||||
if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out OutgoingPacket ackedPacket))
|
||||
{
|
||||
m_packets.Remove(pendingAcknowledgement.SequenceNumber);
|
||||
if (ackedPacket != null)
|
||||
{
|
||||
// Update stats
|
||||
if(ackedPacket.Buffer != null)
|
||||
{
|
||||
Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
|
||||
|
||||
ackedPacket.Client.FreeUDPBuffer(ackedPacket.Buffer);
|
||||
ackedPacket.Buffer = null;
|
||||
}
|
||||
// As with other network applications, assume that an acknowledged packet is an
|
||||
// indication that the network can handle a little more load, speed up the transmission
|
||||
ackedPacket.Client.FlowThrottle.AcknowledgePackets(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue