From 155da5aad2dc0bb6d88d7276e9e3a12639cf9ead Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Wed, 21 Jan 2015 20:31:42 +0000
Subject: Add debug ability to ignore reliably sent packets that are not
 acknowledged.

This is controlled via the console command "debug lludp client set process-unacked-sends true [<avatar-first-name> <avatar-last-name>]"
For debug purposes to see if this process for very bad connections is causing general outbound udp processing delays.
Relates to http://opensimulator.org/mantis/view.php?id=7393
---
 .../Region/ClientStack/Linden/UDP/LLUDPClient.cs   |  9 +++
 .../Region/ClientStack/Linden/UDP/LLUDPServer.cs   | 47 ++++++-----
 .../ClientStack/Linden/UDP/LLUDPServerCommands.cs  | 93 ++++++++++++++++++++++
 3 files changed, 129 insertions(+), 20 deletions(-)

diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index ce6e3ee..0394e54 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -119,8 +119,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
         public readonly uint CircuitCode;
         /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
         public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
+
+        /// <summary>
+        /// If true then we take action in response to unacked reliably sent packets such as resending the packet.
+        /// </summary>
+        public bool ProcessUnackedSends { get; set; }
+
         /// <summary>Packets we have sent that need to be ACKed by the client</summary>
         public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
+
         /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
         public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>();
 
@@ -225,6 +232,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             if (maxRTO != 0)
                 m_maxRTO = maxRTO;
 
+            ProcessUnackedSends = true;
+
             // Create a token bucket throttle for this client that has the scene token bucket as a parent
             m_throttleClient 
                 = new AdaptiveTokenBucket(
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 4fec91f..ad83b42 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -1137,7 +1137,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
                 outgoingPacket.SequenceNumber = sequenceNumber;
 
-                if (isReliable)
+                if (udpClient.ProcessUnackedSends && isReliable)
                 {
                     // Add this packet to the list of ACK responses we are waiting on from the server
                     udpClient.NeedAcks.Add(outgoingPacket);
@@ -1325,30 +1325,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
             #region ACK Receiving
 
-            // Handle appended ACKs
-            if (packet.Header.AppendedAcks && packet.Header.AckList != null)
+            if (udpClient.ProcessUnackedSends)
             {
-//                m_log.DebugFormat(
-//                    "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
-//                    packet.Header.AckList.Length, client.Name, m_scene.Name);
+                // Handle appended ACKs
+                if (packet.Header.AppendedAcks && packet.Header.AckList != null)
+                {
+    //                m_log.DebugFormat(
+    //                    "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
+    //                    packet.Header.AckList.Length, client.Name, m_scene.Name);
 
-                for (int i = 0; i < packet.Header.AckList.Length; i++)
-                    udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
-            }
+                    for (int i = 0; i < packet.Header.AckList.Length; i++)
+                        udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
+                }
 
-            // Handle PacketAck packets
-            if (packet.Type == PacketType.PacketAck)
-            {
-                PacketAckPacket ackPacket = (PacketAckPacket)packet;
+                // Handle PacketAck packets
+                if (packet.Type == PacketType.PacketAck)
+                {
+                    PacketAckPacket ackPacket = (PacketAckPacket)packet;
 
-//                m_log.DebugFormat(
-//                    "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
-//                    ackPacket.Packets.Length, client.Name, m_scene.Name);
+    //                m_log.DebugFormat(
+    //                    "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
+    //                    ackPacket.Packets.Length, client.Name, m_scene.Name);
 
-                for (int i = 0; i < ackPacket.Packets.Length; i++)
-                    udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
+                    for (int i = 0; i < ackPacket.Packets.Length; i++)
+                        udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
 
-                // We don't need to do anything else with PacketAck packets
+                    // We don't need to do anything else with PacketAck packets
+                    return;
+                }
+            }
+            else if (packet.Type == PacketType.PacketAck)
+            {
                 return;
             }
 
@@ -2011,7 +2018,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
                     if (udpClient.IsConnected)
                     {
-                        if (m_resendUnacked)
+                        if (udpClient.ProcessUnackedSends && m_resendUnacked)
                             HandleUnacked(llClient);
 
                         if (m_sendAcks)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
index 17a394d..ac6c0b4 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
@@ -195,6 +195,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                 "Start, stop or get status of OutgoingQueueRefillEngine.",
                 "If stopped then refill requests are processed directly via the threadpool.",
                 HandleOqreCommand);
+
+            m_console.Commands.AddCommand(
+                "Debug",
+                false,
+                "debug lludp client get",
+                "debug lludp client get [<avatar-first-name> <avatar-last-name>]",
+                "Get debug parameters for the client.  If no name is given then all client information is returned.",
+                "process-unacked-sends - Do we take action if a sent reliable packet has not been acked.",
+                HandleClientGetCommand);
+
+            m_console.Commands.AddCommand(
+                "Debug", 
+                false, 
+                "debug lludp client set",
+                "debug lludp client set <param> <value> [<avatar-first-name> <avatar-last-name>]",
+                "Set a debug parameter for a particular client.  If no name is given then the value is set on all clients.",
+                "process-unacked-sends - Do we take action if a sent reliable packet has not been acked.",
+                HandleClientSetCommand);
         }
 
         private void HandleShowServerThrottlesCommand(string module, string[] args)
@@ -538,6 +556,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             m_console.OutputFormat("{0} set to {1} in {2}", param, rawValue, m_udpServer.Scene.Name);
         }
 
+        private void HandleClientGetCommand(string module, string[] args)
+        {
+            if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
+                return;
+
+            if (args.Length != 4 && args.Length != 6)
+            {
+                MainConsole.Instance.OutputFormat("Usage: debug lludp client get [<avatar-first-name> <avatar-last-name>]");
+                return;
+            }
+
+            string name = null;
+
+            if (args.Length == 6)
+                name = string.Format("{0} {1}", args[4], args[5]);
+
+            m_udpServer.Scene.ForEachScenePresence(
+                sp =>
+                {
+                    if ((name == null || sp.Name == name) && sp.ControllingClient is LLClientView)
+                    {
+                        LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
+
+                        m_console.OutputFormat(
+                            "Client debug parameters for {0} ({1}) in {2}",
+                            sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name);
+
+                        ConsoleDisplayList cdl = new ConsoleDisplayList();
+                        cdl.AddRow("process-unacked-sends", udpClient.ProcessUnackedSends);
+
+                        m_console.Output(cdl.ToString());
+                    }
+                });
+        }
+
+        private void HandleClientSetCommand(string module, string[] args)
+        {
+            if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
+                return;
+
+            if (args.Length != 6 && args.Length != 8)
+            {
+                MainConsole.Instance.OutputFormat("Usage: debug lludp client set <param> <value> [<avatar-first-name> <avatar-last-name>]");
+                return;
+            }        
+
+            string param = args[4];
+            string rawValue = args[5];
+
+            string name = null;
+
+            if (args.Length == 8)
+                name = string.Format("{0} {1}", args[6], args[7]);
+
+            if (param == "process-unacked-sends")
+            {
+                bool newValue;
+
+                if (!ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, rawValue, out newValue))
+                    return;
+
+                m_udpServer.Scene.ForEachScenePresence(
+                    sp =>
+                    {
+                        if ((name == null || sp.Name == name) && sp.ControllingClient is LLClientView)
+                        {
+                            LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
+                            udpClient.ProcessUnackedSends = newValue;
+
+                            m_console.OutputFormat("{0} set to {1} for {2} in {3}", param, newValue, sp.Name, m_udpServer.Scene.Name);
+                        }
+                    });
+            }
+        }
+
         private void HandlePacketCommand(string module, string[] args)
         {
             if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
-- 
cgit v1.1