From 35ec496f98ff41a6ded4eafa09a0587ef57d1527 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 17 Dec 2008 17:19:14 +0000 Subject: Revamp packet handler to smooth out the stream of resent packets. Eliminates the bursting in resends observed in the prior implementation --- .../ClientStack/LindenUDP/LLPacketHandler.cs | 104 ++++++++++++--------- 1 file changed, 61 insertions(+), 43 deletions(-) (limited to 'OpenSim/Region/ClientStack/LindenUDP') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs index 9dbb00b..4e8d4f9 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs @@ -54,7 +54,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP int PacketsReceived { get; } int PacketsReceivedReported { get; } - uint SilenceLimit { get; set; } uint ResendTimeout { get; set; } bool ReliableIsImportant { get; set; } int MaxReliableResends { get; set; } @@ -124,7 +123,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// The number of milliseconds that can pass before a packet that needs an ack is resent. /// - private uint m_ResendTimeout = 2000; + private uint m_ResendTimeout = 4000; public uint ResendTimeout { @@ -132,14 +131,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP 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; public int MaxReliableResends @@ -148,8 +139,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP set { m_MaxReliableResends = value; } } - private int m_LastAck = 0; - // Track duplicated packets. This uses a Dictionary. Both insertion // and lookup are common operations and need to take advantage of // 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_UnackedBytes = 0; + private int m_LastResend = 0; + public int PacketsReceived { get { return m_PacketsReceived; } @@ -211,6 +202,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP set { m_ReliableIsImportant = value; } } + private int m_DropSafeTimeout; + LLPacketServer m_PacketServer; private byte[] m_ZeroOutBuffer = new byte[4096]; @@ -222,6 +215,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { m_Client = client; m_PacketServer = server; + m_DropSafeTimeout = System.Environment.TickCount + 15000; m_PacketQueue = new LLPacketQueue(client.AgentId, userSettings); @@ -235,6 +229,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_PacketQueue.Enqueue(null); m_PacketQueue.Close(); + m_Client = null; } // Send one packet. This actually doesn't send anything, it queues @@ -327,15 +322,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void ResendUnacked() { 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 + (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 // anything. There may not be a client there, don't clog up the // pipes. // - if (lastAck == 0) - return; - lock (m_NeedAck) { // Nothing to do @@ -343,16 +362,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (m_NeedAck.Count == 0) return; - // If we have seen no acks in s but are - // 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; - } + int resent = 0; foreach (AckData data in new List(m_NeedAck.Values)) { @@ -362,25 +372,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP // if ((now - data.TickCount) > m_ResendTimeout) { - m_NeedAck[packet.Header.Sequence].Resends++; + if (resent < 20) + { + m_NeedAck[packet.Header.Sequence].Resends++; - // 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; + // 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; - } + 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; - m_NeedAck[packet.Header.Sequence].TickCount = - System.Environment.TickCount; + QueuePacket(packet, ThrottleOutPacketType.Resend, + data.Identifier); - QueuePacket(packet, ThrottleOutPacketType.Resend, - data.Identifier); + resent++; + } + else + { + m_NeedAck[packet.Header.Sequence].TickCount += + intervalMs; + } } } } @@ -623,8 +643,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_NeedAck.Remove(id); m_UnackedBytes -= packet.ToBytes().Length; - - m_LastAck = System.Environment.TickCount; } } -- cgit v1.1