From 066a6fbaa1ff1a07d181db389a24235fd55e63c9 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 18 Dec 2019 23:26:13 +0000 Subject: changes on lludp acks and resends --- .../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 2 +- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 28 ++-- .../Region/ClientStack/Linden/UDP/LLUDPClient.cs | 175 +++++++++++---------- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 29 ++-- .../Linden/UDP/UnackedPacketCollection.cs | 123 ++++++++------- 5 files changed, 186 insertions(+), 171 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 316d39d..35e18a0 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -411,7 +411,7 @@ namespace OpenSim.Region.ClientStack.Linden { try { -// m_log.Debug("[CAPS]: ScriptTaskInventory Request in region: " + m_regionName); + //m_log.Debug("[CAPS]: ScriptTaskInventory Request in region: " + m_regionName); //m_log.DebugFormat("[CAPS]: request: {0}, path: {1}, param: {2}", request, path, param); Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 645d00b..d0902ff 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -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(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); } /// @@ -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); } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 69e53f6..af62d9c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -115,7 +115,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Circuit code that this client is connected on public readonly uint CircuitCode; /// Sequence numbers of packets we've received (for duplicate checking) - public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(256); + public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(1024); /// Packets we have sent that need to be ACKed by the client public UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); @@ -123,6 +123,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// ACKs that are queued up, waiting to be sent to the client public DoubleLocklessQueue PendingAcks = new DoubleLocklessQueue(); + public int AckStalls; + /// Current packet sequence number public int CurrentSequence; /// Current ping sequence number @@ -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,46 +541,20 @@ 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. /// - 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 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; - } + queue.Enqueue(packet, highPriority); + return true; } else { @@ -608,33 +585,84 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutgoingPacket packet = null; DoubleLocklessQueue 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(); + } + } + + 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,55 +675,34 @@ 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 + if (packet.Buffer == null) { - m_packetOutboxes[i] = new DoubleLocklessQueue(); + // packet canceled elsewhere (by a ack for example) + if (queue.Count < 5) + emptyCategories |= CategoryToFlag(i); + continue; } - if (success) + + if (m_throttleCategories[i].RemoveTokens(packet.Buffer.DataLength)) { - // 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); - } - else - { - if (bucket.RemoveTokens(packet.Buffer.DataLength)) - { - // Send the packet - m_udpServer.SendPacketFinal(packet); - packetSent = true; - - if (queue.Count < 5) - emptyCategories |= CategoryToFlag(i); - } - else - { - // Save the dequeued packet for the next iteration - m_nextPackets[i] = packet; - } - } + // Send the packet + m_udpServer.SendPacketFinal(packet); + packetSent = true; + if (queue.Count < 5) + emptyCategories |= CategoryToFlag(i); } else { - // No packets in this queue. Fire the queue empty callback - // if it has not been called recently - emptyCategories |= CategoryToFlag(i); + // Save the dequeued packet for the next iteration + m_nextPackets[i] = packet; } } else { - m_packetOutboxes[i] = new DoubleLocklessQueue(); + // No packets in this queue. Fire the queue empty callback + // if it has not been called recently emptyCategories |= CategoryToFlag(i); } } @@ -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; } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 2863b8d..6994efb 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -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 diff --git a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs index 32a6c40..af5b2ae 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs @@ -66,21 +66,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// Holds the actual unacked packet data, sorted by sequence number - private Dictionary m_packets = new Dictionary(); + private SortedDictionary m_packets = new SortedDictionary(); /// Holds packets that need to be added to the unacknowledged list private LocklessQueue m_pendingAdds = new LocklessQueue(); /// Holds information about pending acknowledgements private LocklessQueue m_pendingAcknowledgements = new LocklessQueue(); /// Holds information about pending removals private LocklessQueue m_pendingRemoves = new LocklessQueue(); - - + 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; } /// @@ -148,33 +158,47 @@ namespace OpenSim.Region.ClientStack.LindenUDP ProcessQueues(); List 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) { - if (expiredPackets == null) - expiredPackets = new List(); + int t = Interlocked.Exchange(ref packet.TickCount, ptime); + if (t > ptime) + Interlocked.Exchange(ref packet.TickCount, t); + continue; + } - // The TickCount will be set to the current time when the packet - // is actually sent out again - packet.TickCount = 0; + if (expiredPackets == null) + expiredPackets = new List(); - // As with other network applications, assume that an expired packet is - // an indication of some network problem, slow transmission - packet.Client.FlowThrottle.ExpirePackets(1); + // As with other network applications, assume that an expired packet is + // an indication of some network problem, slow transmission + packet.Client.FlowThrottle.ExpirePackets(1); - expiredPackets.Add(packet); - } + expiredPackets.Add(packet); } } @@ -186,65 +210,50 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void ProcessQueues() { + while (m_pendingRemoves.TryDequeue(out uint pendingRemove)) + { + 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); + + removedPacket.Client.FreeUDPBuffer(removedPacket.Buffer); + removedPacket.Buffer = null; + } + } + } + // Process all the pending adds - OutgoingPacket pendingAdd; - while (m_pendingAdds.TryDequeue(out pendingAdd)) + 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 - PendingAck pendingAcknowledgement; - while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement)) + while (m_pendingAcknowledgements.TryDequeue(out PendingAck pendingAcknowledgement)) { //m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Processing ack {0}", pendingAcknowledgement.SequenceNumber); - OutgoingPacket ackedPacket; - if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket)) + if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out OutgoingPacket ackedPacket)) { + m_packets.Remove(pendingAcknowledgement.SequenceNumber); 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; + 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); } - 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) - { - m_packets.Remove(pendingRemove); - - // Update stats - Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength); - - removedPacket.Client.FreeUDPBuffer(removedPacket.Buffer); - removedPacket.Buffer = null; - } } } } -- cgit v1.1