aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs126
1 files changed, 95 insertions, 31 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index e52ac37..fe31bd9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -31,6 +31,7 @@ using System.Net;
31using System.Threading; 31using System.Threading;
32using log4net; 32using log4net;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
36 37
@@ -81,6 +82,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
81 /// hooked to put more data on the empty queue</summary> 82 /// hooked to put more data on the empty queue</summary>
82 public event QueueEmpty OnQueueEmpty; 83 public event QueueEmpty OnQueueEmpty;
83 84
85 public event Func<ThrottleOutPacketTypeFlags, bool> HasUpdates;
86
84 /// <summary>AgentID for this client</summary> 87 /// <summary>AgentID for this client</summary>
85 public readonly UUID AgentID; 88 public readonly UUID AgentID;
86 /// <summary>The remote address of the connected client</summary> 89 /// <summary>The remote address of the connected client</summary>
@@ -160,6 +163,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
160 private int m_maxRTO = 60000; 163 private int m_maxRTO = 60000;
161 public bool m_deliverPackets = true; 164 public bool m_deliverPackets = true;
162 165
166 public int m_lastStartpingTimeMS;
167 public int m_pingMS;
168
169 public int PingTimeMS
170 {
171 get
172 {
173 if (m_pingMS < 10)
174 return 10;
175 if(m_pingMS > 2000)
176 return 2000;
177 return m_pingMS;
178 }
179 }
180
181 /// <summary>
182 /// This is the percentage of the udp texture queue to add to the task queue since
183 /// textures are now generally handled through http.
184 /// </summary>
185 private double m_cannibalrate = 0.0;
186
187 private ClientInfo m_info = new ClientInfo();
188
163 /// <summary> 189 /// <summary>
164 /// Default constructor 190 /// Default constructor
165 /// </summary> 191 /// </summary>
@@ -197,6 +223,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
197 // Create an array of token buckets for this clients different throttle categories 223 // Create an array of token buckets for this clients different throttle categories
198 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 224 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
199 225
226 m_cannibalrate = rates.CannibalizeTextureRate;
227
200 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 228 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
201 { 229 {
202 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 230 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
@@ -212,6 +240,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
212 240
213 // Initialize this to a sane value to prevent early disconnects 241 // Initialize this to a sane value to prevent early disconnects
214 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; 242 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
243 m_pingMS = (int)(3.0 * server.TickCountResolution); // so filter doesnt start at 0;
215 } 244 }
216 245
217 /// <summary> 246 /// <summary>
@@ -241,20 +270,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
241 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists 270 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
242 // of pending and needed ACKs for every client every time some method wants information about 271 // of pending and needed ACKs for every client every time some method wants information about
243 // this connection is a recipe for poor performance 272 // this connection is a recipe for poor performance
244 ClientInfo info = new ClientInfo(); 273
245 info.pendingAcks = new Dictionary<uint, uint>(); 274 m_info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate;
246 info.needAck = new Dictionary<uint, byte[]>(); 275 m_info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
247 276 m_info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
248 info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; 277 m_info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
249 info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; 278 m_info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
250 info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; 279 m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
251 info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; 280 m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
252 info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; 281 m_info.totalThrottle = (int)m_throttleCategory.DripRate;
253 info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 282
254 info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 283 return m_info;
255 info.totalThrottle = (int)m_throttleCategory.DripRate;
256
257 return info;
258 } 284 }
259 285
260 /// <summary> 286 /// <summary>
@@ -348,6 +374,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
348 texture = Math.Max(texture, LLUDPServer.MTU); 374 texture = Math.Max(texture, LLUDPServer.MTU);
349 asset = Math.Max(asset, LLUDPServer.MTU); 375 asset = Math.Max(asset, LLUDPServer.MTU);
350 376
377 // Since most textures are now delivered through http, make it possible
378 // to cannibalize some of the bw from the texture throttle to use for
379 // the task queue (e.g. object updates)
380 task = task + (int)(m_cannibalrate * texture);
381 texture = (int)((1 - m_cannibalrate) * texture);
382
351 //int total = resend + land + wind + cloud + task + texture + asset; 383 //int total = resend + land + wind + cloud + task + texture + asset;
352 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", 384 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
353 // AgentID, resend, land, wind, cloud, task, texture, asset, total); 385 // AgentID, resend, land, wind, cloud, task, texture, asset, total);
@@ -646,15 +678,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
646 /// <param name="categories">Throttle categories to fire the callback for</param> 678 /// <param name="categories">Throttle categories to fire the callback for</param>
647 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories) 679 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
648 { 680 {
649 if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) 681// if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
682 if (!m_isQueueEmptyRunning && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
650 { 683 {
684 m_isQueueEmptyRunning = true;
685
686 int start = Environment.TickCount & Int32.MaxValue;
687 const int MIN_CALLBACK_MS = 30;
688
689 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
690 if (m_nextOnQueueEmpty == 0)
691 m_nextOnQueueEmpty = 1;
692
651 // Use a value of 0 to signal that FireQueueEmpty is running 693 // Use a value of 0 to signal that FireQueueEmpty is running
652 m_nextOnQueueEmpty = 0; 694// m_nextOnQueueEmpty = 0;
653 // Asynchronously run the callback 695
654 Util.FireAndForget(FireQueueEmpty, categories); 696 m_categories = categories;
697
698 if (HasUpdates(m_categories))
699 {
700 // Asynchronously run the callback
701 Util.FireAndForget(FireQueueEmpty, categories);
702 }
703 else
704 {
705 m_isQueueEmptyRunning = false;
706 }
655 } 707 }
656 } 708 }
657 709
710 private bool m_isQueueEmptyRunning;
711 private ThrottleOutPacketTypeFlags m_categories = 0;
712
658 /// <summary> 713 /// <summary>
659 /// Fires the OnQueueEmpty callback and sets the minimum time that it 714 /// Fires the OnQueueEmpty callback and sets the minimum time that it
660 /// can be called again 715 /// can be called again
@@ -664,22 +719,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
664 /// signature</param> 719 /// signature</param>
665 private void FireQueueEmpty(object o) 720 private void FireQueueEmpty(object o)
666 { 721 {
667 const int MIN_CALLBACK_MS = 30; 722// int start = Environment.TickCount & Int32.MaxValue;
723// const int MIN_CALLBACK_MS = 30;
668 724
669 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; 725// if (m_udpServer.IsRunningOutbound)
670 QueueEmpty callback = OnQueueEmpty; 726// {
671 727 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
672 int start = Environment.TickCount & Int32.MaxValue; 728 QueueEmpty callback = OnQueueEmpty;
673 729
674 if (callback != null) 730 if (callback != null)
675 { 731 {
676 try { callback(categories); } 732// if (m_udpServer.IsRunningOutbound)
677 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); } 733// {
678 } 734 try { callback(categories); }
735 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
736// }
737 }
738// }
739
740// m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
741// if (m_nextOnQueueEmpty == 0)
742// m_nextOnQueueEmpty = 1;
743
744// }
679 745
680 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; 746 m_isQueueEmptyRunning = false;
681 if (m_nextOnQueueEmpty == 0)
682 m_nextOnQueueEmpty = 1;
683 } 747 }
684 internal void ForceThrottleSetting(int throttle, int setting) 748 internal void ForceThrottleSetting(int throttle, int setting)
685 { 749 {