diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6f429905d1..da30a04ab9 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3824,6 +3824,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); } + + /// + /// Requeue an EntityUpdate when it was not acknowledged by the client. + /// We will update the priority and put it in the correct queue, merging update flags + /// with any other updates that may be queued for the same entity. + /// The original update time is used for the merged update. + /// + private void ResendPrimUpdate(EntityUpdate update) + { + // If the update exists in priority queue, it will be updated. + // If it does not exist then it will be added with the current (rather than its original) priority + uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity); + + lock (m_entityUpdates.SyncRoot) + m_entityUpdates.Enqueue(priority, update); + } + + /// + /// Requeue a list of EntityUpdates when they were not acknowledged by the client. + /// We will update the priority and put it in the correct queue, merging update flags + /// with any other updates that may be queued for the same entity. + /// The original update time is used for the merged update. + /// + private void ResendPrimUpdates(List updates, OutgoingPacket oPacket) + { + // m_log.WarnFormat("[CLIENT] resending prim updates {0}, packet sequence number {1}", updates[0].UpdateTime, oPacket.SequenceNumber); + + // Remove the update packet from the list of packets waiting for acknowledgement + // because we are requeuing the list of updates. They will be resent in new packets + // with the most recent state and priority. + m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); + + // Count this as a resent packet since we are going to requeue all of the updates contained in it + Interlocked.Increment(ref m_udpClient.PacketsResent); + + // We're not going to worry about interlock yet since its not currently critical that this total count + // is 100% correct + m_udpServer.PacketsResentCount++; + + foreach (EntityUpdate update in updates) + ResendPrimUpdate(update); + } + private void ProcessEntityUpdates(int maxUpdates) { OpenSim.Framework.Lazy> objectUpdateBlocks = new OpenSim.Framework.Lazy>(); @@ -4044,7 +4087,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < blocks.Count; i++) packet.ObjectData[i] = blocks[i]; - OutPacket(packet, ThrottleOutPacketType.Unknown, true); + OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); } if (objectUpdateBlocks.IsValueCreated) @@ -4090,8 +4133,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < blocks.Count; i++) packet.ObjectData[i] = blocks[i]; - - OutPacket(packet, ThrottleOutPacketType.Task, true); + + OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); } #endregion Packet Sending diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 99e7aba1d0..f66534df0e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1245,7 +1245,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP int dataLength = buffer.DataLength; // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here - if (!isZerocoded && !isResend) + if (!isZerocoded && !isResend && outgoingPacket.UnackedMethod == null) { // Keep appending ACKs until there is no room left in the buffer or there are // no more ACKs to append