aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorMelanie Thielker2008-12-17 17:19:14 +0000
committerMelanie Thielker2008-12-17 17:19:14 +0000
commit35ec496f98ff41a6ded4eafa09a0587ef57d1527 (patch)
tree4b8b8c3f68ccc9e322f4ea117c1a917b1a4fb6e7 /OpenSim/Region
parent* Replace manually zeroing with Array.Clear(). Thanks cmickeyb (diff)
downloadopensim-SC-35ec496f98ff41a6ded4eafa09a0587ef57d1527.zip
opensim-SC-35ec496f98ff41a6ded4eafa09a0587ef57d1527.tar.gz
opensim-SC-35ec496f98ff41a6ded4eafa09a0587ef57d1527.tar.bz2
opensim-SC-35ec496f98ff41a6ded4eafa09a0587ef57d1527.tar.xz
Revamp packet handler to smooth out the stream of resent packets.
Eliminates the bursting in resends observed in the prior implementation
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs104
1 files changed, 61 insertions, 43 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs
index 9dbb00b..4e8d4f9 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs
@@ -54,7 +54,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
54 54
55 int PacketsReceived { get; } 55 int PacketsReceived { get; }
56 int PacketsReceivedReported { get; } 56 int PacketsReceivedReported { get; }
57 uint SilenceLimit { get; set; }
58 uint ResendTimeout { get; set; } 57 uint ResendTimeout { get; set; }
59 bool ReliableIsImportant { get; set; } 58 bool ReliableIsImportant { get; set; }
60 int MaxReliableResends { get; set; } 59 int MaxReliableResends { get; set; }
@@ -124,7 +123,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
124 /// <summary> 123 /// <summary>
125 /// The number of milliseconds that can pass before a packet that needs an ack is resent. 124 /// The number of milliseconds that can pass before a packet that needs an ack is resent.
126 /// </param> 125 /// </param>
127 private uint m_ResendTimeout = 2000; 126 private uint m_ResendTimeout = 4000;
128 127
129 public uint ResendTimeout 128 public uint ResendTimeout
130 { 129 {
@@ -132,14 +131,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
132 set { m_ResendTimeout = value; } 131 set { m_ResendTimeout = value; }
133 } 132 }
134 133
135 private uint m_SilenceLimit = 250;
136
137 public uint SilenceLimit
138 {
139 get { return m_SilenceLimit; }
140 set { m_SilenceLimit = value; }
141 }
142
143 private int m_MaxReliableResends = 3; 134 private int m_MaxReliableResends = 3;
144 135
145 public int MaxReliableResends 136 public int MaxReliableResends
@@ -148,8 +139,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
148 set { m_MaxReliableResends = value; } 139 set { m_MaxReliableResends = value; }
149 } 140 }
150 141
151 private int m_LastAck = 0;
152
153 // Track duplicated packets. This uses a Dictionary. Both insertion 142 // Track duplicated packets. This uses a Dictionary. Both insertion
154 // and lookup are common operations and need to take advantage of 143 // and lookup are common operations and need to take advantage of
155 // the hashing. Expiration is less common and can be allowed the 144 // the hashing. Expiration is less common and can be allowed the
@@ -168,6 +157,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
168 private int m_PacketsSentReported = 0; 157 private int m_PacketsSentReported = 0;
169 private int m_UnackedBytes = 0; 158 private int m_UnackedBytes = 0;
170 159
160 private int m_LastResend = 0;
161
171 public int PacketsReceived 162 public int PacketsReceived
172 { 163 {
173 get { return m_PacketsReceived; } 164 get { return m_PacketsReceived; }
@@ -211,6 +202,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
211 set { m_ReliableIsImportant = value; } 202 set { m_ReliableIsImportant = value; }
212 } 203 }
213 204
205 private int m_DropSafeTimeout;
206
214 LLPacketServer m_PacketServer; 207 LLPacketServer m_PacketServer;
215 private byte[] m_ZeroOutBuffer = new byte[4096]; 208 private byte[] m_ZeroOutBuffer = new byte[4096];
216 209
@@ -222,6 +215,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
222 { 215 {
223 m_Client = client; 216 m_Client = client;
224 m_PacketServer = server; 217 m_PacketServer = server;
218 m_DropSafeTimeout = System.Environment.TickCount + 15000;
225 219
226 m_PacketQueue = new LLPacketQueue(client.AgentId, userSettings); 220 m_PacketQueue = new LLPacketQueue(client.AgentId, userSettings);
227 221
@@ -235,6 +229,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
235 229
236 m_PacketQueue.Enqueue(null); 230 m_PacketQueue.Enqueue(null);
237 m_PacketQueue.Close(); 231 m_PacketQueue.Close();
232 m_Client = null;
238 } 233 }
239 234
240 // Send one packet. This actually doesn't send anything, it queues 235 // Send one packet. This actually doesn't send anything, it queues
@@ -327,15 +322,39 @@ namespace OpenSim.Region.ClientStack.LindenUDP
327 private void ResendUnacked() 322 private void ResendUnacked()
328 { 323 {
329 int now = System.Environment.TickCount; 324 int now = System.Environment.TickCount;
330 int lastAck = m_LastAck; 325
326 int intervalMs = 250;
327
328 if (m_LastResend != 0)
329 intervalMs = now - m_LastResend;
330
331 lock (m_NeedAck)
332 {
333 if (m_DropSafeTimeout > now ||
334 intervalMs > 500) // We were frozen!
335 {
336 foreach (AckData data in new List<AckData>
337 (m_NeedAck.Values))
338 {
339 if (m_DropSafeTimeout > now)
340 {
341 m_NeedAck[data.Packet.Header.Sequence].
342 TickCount = now;
343 }
344 else
345 {
346 m_NeedAck[data.Packet.Header.Sequence].
347 TickCount += intervalMs;
348 }
349 }
350 }
351 }
352 m_LastResend = now;
331 353
332 // Unless we have received at least one ack, don't bother resending 354 // Unless we have received at least one ack, don't bother resending
333 // anything. There may not be a client there, don't clog up the 355 // anything. There may not be a client there, don't clog up the
334 // pipes. 356 // pipes.
335 // 357 //
336 if (lastAck == 0)
337 return;
338
339 lock (m_NeedAck) 358 lock (m_NeedAck)
340 { 359 {
341 // Nothing to do 360 // Nothing to do
@@ -343,16 +362,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
343 if (m_NeedAck.Count == 0) 362 if (m_NeedAck.Count == 0)
344 return; 363 return;
345 364
346 // If we have seen no acks in <SilenceLimit> s but are 365 int resent = 0;
347 // waiting for acks, then there may be no one listening.
348 // No need to resend anything. Keep it until it gets stale,
349 // then it will be dropped.
350 //
351 if ((((now - lastAck) > m_SilenceLimit) &&
352 m_NeedAck.Count > 0) || m_NeedAck.Count == 0)
353 {
354 return;
355 }
356 366
357 foreach (AckData data in new List<AckData>(m_NeedAck.Values)) 367 foreach (AckData data in new List<AckData>(m_NeedAck.Values))
358 { 368 {
@@ -362,25 +372,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
362 // 372 //
363 if ((now - data.TickCount) > m_ResendTimeout) 373 if ((now - data.TickCount) > m_ResendTimeout)
364 { 374 {
365 m_NeedAck[packet.Header.Sequence].Resends++; 375 if (resent < 20)
376 {
377 m_NeedAck[packet.Header.Sequence].Resends++;
366 378
367 // The client needs to be told that a packet is being resent, otherwise it appears to believe 379 // The client needs to be told that a packet is being resent, otherwise it appears to believe
368 // that it should reset its sequence to that packet number. 380 // that it should reset its sequence to that packet number.
369 packet.Header.Resent = true; 381 packet.Header.Resent = true;
370 382
371 if (m_NeedAck[packet.Header.Sequence].Resends >= 383 if ((m_NeedAck[packet.Header.Sequence].Resends >=
372 m_MaxReliableResends && (!m_ReliableIsImportant)) 384 m_MaxReliableResends) && (!m_ReliableIsImportant))
373 { 385 {
374 m_NeedAck.Remove(packet.Header.Sequence); 386 m_NeedAck.Remove(packet.Header.Sequence);
375 TriggerOnPacketDrop(packet, data.Identifier); 387 TriggerOnPacketDrop(packet, data.Identifier);
376 continue; 388 continue;
377 } 389 }
390
391 m_NeedAck[packet.Header.Sequence].TickCount =
392 System.Environment.TickCount;
378 393
379 m_NeedAck[packet.Header.Sequence].TickCount = 394 QueuePacket(packet, ThrottleOutPacketType.Resend,
380 System.Environment.TickCount; 395 data.Identifier);
381 396
382 QueuePacket(packet, ThrottleOutPacketType.Resend, 397 resent++;
383 data.Identifier); 398 }
399 else
400 {
401 m_NeedAck[packet.Header.Sequence].TickCount +=
402 intervalMs;
403 }
384 } 404 }
385 } 405 }
386 } 406 }
@@ -623,8 +643,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
623 643
624 m_NeedAck.Remove(id); 644 m_NeedAck.Remove(id);
625 m_UnackedBytes -= packet.ToBytes().Length; 645 m_UnackedBytes -= packet.ToBytes().Length;
626
627 m_LastAck = System.Environment.TickCount;
628 } 646 }
629 } 647 }
630 648