diff options
author | Melanie Thielker | 2008-12-17 17:19:14 +0000 |
---|---|---|
committer | Melanie Thielker | 2008-12-17 17:19:14 +0000 |
commit | 35ec496f98ff41a6ded4eafa09a0587ef57d1527 (patch) | |
tree | 4b8b8c3f68ccc9e322f4ea117c1a917b1a4fb6e7 | |
parent | * Replace manually zeroing with Array.Clear(). Thanks cmickeyb (diff) | |
download | opensim-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
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs | 104 |
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 | ||