* 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
prioritization
John Hurliman 2009-10-21 13:47:16 -07:00
parent 9178537e94
commit 7ee422a344
3 changed files with 49 additions and 13 deletions

View File

@ -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");
}

View File

@ -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;

View File

@ -85,6 +85,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="sequenceNumber">Sequence number of the packet to
/// acknowledge</param>
/// <param name="currentTime">Current value of Environment.TickCount</param>
/// <remarks>This does not immediately acknowledge the packet, it only
/// queues the ack so it can be handled in a thread-safe way later</remarks>
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<OutgoingPacket>();
expiredPackets.Add(packet);
}
else
/*else
{
break;
}
}*/
}
}