From 7ee422a344ff22cf988aea2355628d2dee831983 Mon Sep 17 00:00:00 2001
From: John Hurliman
Date: Wed, 21 Oct 2009 13:47:16 -0700
Subject: * Handle UseCircuitCode packets asynchronously. Adding an agent to a
scene can take several seconds, and was blocking up packet handling in the
meantime * Clamp retransmission timeout values between three and 10 seconds *
Log outgoing time for a packet right after it is sent instead of well before
* Loop through the entire UnackedPacketCollection when looking for expired
packets
---
.../Region/ClientStack/LindenUDP/LLUDPClient.cs | 7 +++-
.../Region/ClientStack/LindenUDP/LLUDPServer.cs | 47 ++++++++++++++++++----
.../LindenUDP/UnackedPacketCollection.cs | 8 ++--
3 files changed, 49 insertions(+), 13 deletions(-)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 458e78d..a43197d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -505,8 +505,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
SRTT = (1.0f - ALPHA) * SRTT + ALPHA * r;
}
- // Always round retransmission timeout up to two seconds
- RTO = Math.Max(2000, (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR)));
+ RTO = (int)(SRTT + Math.Max(m_udpServer.TickCountResolution, K * RTTVAR));
+
+ // Clamp the retransmission timeout to manageable values
+ RTO = Utils.Clamp(RTO, 3000, 10000);
+
//m_log.Debug("[LLUDPCLIENT]: Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " +
// RTTVAR + " based on new RTT of " + r + "ms");
}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index a8ce102..209c0e0 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -381,7 +381,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Disconnect an agent if no packets are received for some time
//FIXME: Make 60 an .ini setting
- if (Environment.TickCount - udpClient.TickLastPacketReceived > 1000 * 60)
+ if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60)
{
m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
@@ -439,9 +439,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (!udpClient.IsConnected)
return;
- // Keep track of when this packet was sent out (right now)
- outgoingPacket.TickCount = Environment.TickCount;
-
#region ACK Appending
int dataLength = buffer.DataLength;
@@ -494,6 +491,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Put the UDP payload on the wire
AsyncBeginSend(buffer);
+
+ // Keep track of when this packet was sent out (right now)
+ outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
}
protected override void PacketReceived(UDPPacketBuffer buffer)
@@ -536,7 +536,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// UseCircuitCode handling
if (packet.Type == PacketType.UseCircuitCode)
{
- AddNewClient((UseCircuitCodePacket)packet, (IPEndPoint)buffer.RemoteEndPoint);
+ Util.FireAndForget(
+ delegate(object o)
+ {
+ IPEndPoint remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
+
+ // Begin the process of adding the client to the simulator
+ AddNewClient((UseCircuitCodePacket)packet, remoteEndPoint);
+
+ // Acknowledge the UseCircuitCode packet
+ SendAckImmediate(remoteEndPoint, packet.Header.Sequence);
+ }
+ );
+ return;
}
// Determine which agent this packet came from
@@ -558,11 +570,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Stats tracking
Interlocked.Increment(ref udpClient.PacketsReceived);
- #region ACK Receiving
-
- int now = Environment.TickCount;
+ int now = Environment.TickCount & Int32.MaxValue;
udpClient.TickLastPacketReceived = now;
+ #region ACK Receiving
+
// Handle appended ACKs
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
{
@@ -650,6 +662,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
}
+ private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber)
+ {
+ PacketAckPacket ack = new PacketAckPacket();
+ ack.Header.Reliable = false;
+ ack.Packets = new PacketAckPacket.PacketsBlock[1];
+ ack.Packets[0] = new PacketAckPacket.PacketsBlock();
+ ack.Packets[0].ID = sequenceNumber;
+
+ byte[] packetData = ack.ToBytes();
+ int length = packetData.Length;
+
+ UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length);
+ buffer.DataLength = length;
+
+ Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);
+
+ AsyncBeginSend(buffer);
+ }
+
private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo)
{
UUID agentID = useCircuitCode.CircuitCode.ID;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
index 12f0c0a..bd5fe1c 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
@@ -85,6 +85,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Sequence number of the packet to
/// acknowledge
/// Current value of Environment.TickCount
+ /// This does not immediately acknowledge the packet, it only
+ /// queues the ack so it can be handled in a thread-safe way later
public void Remove(uint sequenceNumber, int currentTime, bool fromResend)
{
m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
@@ -108,7 +110,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (m_packets.Count > 0)
{
- int now = Environment.TickCount;
+ int now = Environment.TickCount & Int32.MaxValue;
foreach (OutgoingPacket packet in m_packets.Values)
{
@@ -123,10 +125,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
expiredPackets = new List();
expiredPackets.Add(packet);
}
- else
+ /*else
{
break;
- }
+ }*/
}
}
--
cgit v1.1