diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index ce6e3eee57..0394e54197 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;
/// Sequence numbers of packets we've received (for duplicate checking)
public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
+
+ ///
+ /// If true then we take action in response to unacked reliably sent packets such as resending the packet.
+ ///
+ public bool ProcessUnackedSends { get; set; }
+
/// Packets we have sent that need to be ACKed by the client
public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
+
/// ACKs that are queued up, waiting to be sent to the client
public readonly OpenSim.Framework.LocklessQueue PendingAcks = new OpenSim.Framework.LocklessQueue();
@@ -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 4fec91fa3a..ad83b4265b 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;
+
+ // 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);
+
+ // We don't need to do anything else with PacketAck packets
+ return;
+ }
}
-
- // Handle PacketAck packets
- if (packet.Type == PacketType.PacketAck)
+ else 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);
-
- 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
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 17a394d8e7..ac6c0b4251 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 [ ]",
+ "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 [ ]",
+ "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 [ ]");
+ 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 [ ]");
+ 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)