aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs62
1 files changed, 38 insertions, 24 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index b27d8d6..e7707a9 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -59,9 +59,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
59 /// </summary> 59 /// </summary>
60 public sealed class LLUDPClient 60 public sealed class LLUDPClient
61 { 61 {
62 // FIXME: Make this a config setting
63 /// <summary>Percentage of the task throttle category that is allocated to avatar and prim
64 /// state updates</summary>
65 const float STATE_TASK_PERCENTAGE = 0.8f;
66
62 /// <summary>The number of packet categories to throttle on. If a throttle category is added 67 /// <summary>The number of packet categories to throttle on. If a throttle category is added
63 /// or removed, this number must also change</summary> 68 /// or removed, this number must also change</summary>
64 const int THROTTLE_CATEGORY_COUNT = 7; 69 const int THROTTLE_CATEGORY_COUNT = 8;
65 70
66 /// <summary>Fired when updated networking stats are produced for this client</summary> 71 /// <summary>Fired when updated networking stats are produced for this client</summary>
67 public event PacketStats OnPacketStats; 72 public event PacketStats OnPacketStats;
@@ -134,9 +139,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
134 /// <summary>An optimization to store the length of dequeued packets being held 139 /// <summary>An optimization to store the length of dequeued packets being held
135 /// for throttling. This avoids expensive calls to Packet.Length</summary> 140 /// for throttling. This avoids expensive calls to Packet.Length</summary>
136 private readonly int[] nextPacketLengths = new int[THROTTLE_CATEGORY_COUNT]; 141 private readonly int[] nextPacketLengths = new int[THROTTLE_CATEGORY_COUNT];
137 /// <summary>Flags to prevent queue empty callbacks from repeatedly firing
138 /// before the callbacks have a chance to put packets in the queue</summary>
139 private readonly bool[] queueEmptySent = new bool[THROTTLE_CATEGORY_COUNT];
140 /// <summary>A reference to the LLUDPServer that is managing this client</summary> 142 /// <summary>A reference to the LLUDPServer that is managing this client</summary>
141 private readonly LLUDPServer udpServer; 143 private readonly LLUDPServer udpServer;
142 144
@@ -167,9 +169,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
167 throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land); 169 throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land);
168 throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind); 170 throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind);
169 throttleCategories[(int)ThrottleOutPacketType.Cloud] = new TokenBucket(throttle, rates.CloudLimit, rates.Cloud); 171 throttleCategories[(int)ThrottleOutPacketType.Cloud] = new TokenBucket(throttle, rates.CloudLimit, rates.Cloud);
170 throttleCategories[(int)ThrottleOutPacketType.Task] = new TokenBucket(throttle, rates.TaskLimit, rates.Task);
171 throttleCategories[(int)ThrottleOutPacketType.Texture] = new TokenBucket(throttle, rates.TextureLimit, rates.Texture); 172 throttleCategories[(int)ThrottleOutPacketType.Texture] = new TokenBucket(throttle, rates.TextureLimit, rates.Texture);
172 throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset); 173 throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset);
174 // State and Transaction are actually sub-categories of the LLUDP generic "Task" category
175 TokenBucket stateBucket = new TokenBucket(throttle, (int)((float)rates.TaskLimit * STATE_TASK_PERCENTAGE), (int)((float)rates.Task * STATE_TASK_PERCENTAGE));
176 throttleCategories[(int)ThrottleOutPacketType.State] = stateBucket;
177 throttleCategories[(int)ThrottleOutPacketType.Task] = new TokenBucket(throttle, rates.TaskLimit - stateBucket.MaxBurst, rates.Task - stateBucket.DripRate);
173 178
174 // Set the granularity variable used for retransmission calculations to 179 // Set the granularity variable used for retransmission calculations to
175 // the measured resolution of Environment.TickCount 180 // the measured resolution of Environment.TickCount
@@ -177,6 +182,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
177 182
178 // Default the retransmission timeout to three seconds 183 // Default the retransmission timeout to three seconds
179 RTO = 3000; 184 RTO = 3000;
185
186 // Initialize this to a sane value to prevent early disconnects
187 TickLastPacketReceived = Environment.TickCount;
180 } 188 }
181 189
182 /// <summary> 190 /// <summary>
@@ -212,7 +220,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
212 info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; 220 info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
213 info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; 221 info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
214 info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; 222 info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
215 info.taskThrottle = throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; 223 info.taskThrottle = throttleCategories[(int)ThrottleOutPacketType.State].DripRate + throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
216 info.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 224 info.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
217 info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 225 info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
218 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle + 226 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
@@ -309,7 +317,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
309 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; 317 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4;
310 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; 318 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4;
311 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; 319 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4;
312 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Task].DripRate), 0, data, i, 4); i += 4; 320 Buffer.BlockCopy(Utils.FloatToBytes((float)(throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) +
321 throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4;
313 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; 322 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4;
314 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4; 323 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4;
315 324
@@ -318,12 +327,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
318 327
319 public void SetThrottle(ThrottleOutPacketType category, int rate) 328 public void SetThrottle(ThrottleOutPacketType category, int rate)
320 { 329 {
321 int i = (int)category; 330 if (category == ThrottleOutPacketType.Task)
322 if (i >= 0 && i < throttleCategories.Length) 331 {
332 TokenBucket stateBucket = throttleCategories[(int)ThrottleOutPacketType.State];
333 TokenBucket taskBucket = throttleCategories[(int)ThrottleOutPacketType.Task];
334
335 stateBucket.MaxBurst = (int)((float)rate * STATE_TASK_PERCENTAGE);
336 stateBucket.DripRate = (int)((float)rate * STATE_TASK_PERCENTAGE);
337
338 taskBucket.MaxBurst = rate - stateBucket.MaxBurst;
339 taskBucket.DripRate = rate - stateBucket.DripRate;
340 }
341 else
323 { 342 {
324 TokenBucket bucket = throttleCategories[(int)category]; 343 int i = (int)category;
325 bucket.MaxBurst = rate; 344 if (i >= 0 && i < throttleCategories.Length)
326 bucket.DripRate = rate; 345 {
346 TokenBucket bucket = throttleCategories[(int)category];
347 bucket.MaxBurst = rate;
348 bucket.DripRate = rate;
349 }
327 } 350 }
328 } 351 }
329 352
@@ -393,10 +416,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
393 queue = packetOutboxes[i]; 416 queue = packetOutboxes[i];
394 if (queue.Dequeue(out packet)) 417 if (queue.Dequeue(out packet))
395 { 418 {
396 // Reset the flag for firing this queue's OnQueueEmpty callback
397 // now that we have dequeued a packet
398 queueEmptySent[i] = false;
399
400 // A packet was pulled off the queue. See if we have 419 // A packet was pulled off the queue. See if we have
401 // enough tokens in the bucket to send it out 420 // enough tokens in the bucket to send it out
402 if (bucket.RemoveTokens(packet.Buffer.DataLength)) 421 if (bucket.RemoveTokens(packet.Buffer.DataLength))
@@ -458,14 +477,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
458 477
459 private void FireQueueEmpty(int queueIndex) 478 private void FireQueueEmpty(int queueIndex)
460 { 479 {
461 if (!queueEmptySent[queueIndex]) 480 QueueEmpty callback = OnQueueEmpty;
462 { 481 if (callback != null)
463 queueEmptySent[queueIndex] = true; 482 Util.FireAndForget(delegate(object o) { callback((ThrottleOutPacketType)(int)o); }, queueIndex);
464
465 QueueEmpty callback = OnQueueEmpty;
466 if (callback != null)
467 Util.FireAndForget(delegate(object o) { callback((ThrottleOutPacketType)(int)o); }, queueIndex);
468 }
469 } 483 }
470 } 484 }
471} 485}