From e36a700eb0732472ca8675bcc520b20674d9037d Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 2 Nov 2012 14:02:57 +0000 Subject: add debug position on bad primmesh error --- OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs index 76e42d4..dc247a9 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs @@ -1403,8 +1403,8 @@ namespace OpenSim.Region.Physics.OdePlugin if (vertexCount == 0 || indexCount == 0) { - m_log.WarnFormat("[PHYSICS]: Invalid mesh data on OdePrim {0}, mesh {1}", - Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh"); + m_log.WarnFormat("[PHYSICS]: Invalid mesh data on OdePrim {0}, mesh {1} at {2}", + Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh",_position.ToString()); m_hasOBB = false; m_OBBOffset = Vector3.Zero; -- cgit v1.1 From b8c19fe1a9dc49a060be7afce6d317d52db1983a Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 2 Nov 2012 17:40:17 +0000 Subject: Create a new random when needed using normal time based seed instead of reusing a shared one than may not be valid --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index ee61de6..6339522 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -112,7 +112,7 @@ namespace OpenSim.Region.Framework.Scenes private long timeLastChanged = 0; private long m_maxPersistTime = 0; private long m_minPersistTime = 0; - private Random m_rand; +// private Random m_rand; private List m_linkedAvatars = new List(); /// @@ -130,6 +130,7 @@ namespace OpenSim.Region.Framework.Scenes { if (value) { + if (m_isBackedUp) { m_scene.SceneGraph.FireChangeBackup(this); @@ -139,13 +140,15 @@ namespace OpenSim.Region.Framework.Scenes timeFirstChanged = DateTime.Now.Ticks; if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null) { +/* if (m_rand == null) { byte[] val = new byte[16]; m_rootPart.UUID.ToBytes(val, 0); m_rand = new Random(BitConverter.ToInt32(val, 0)); } - + */ + Random m_rand = new Random(); if (m_scene.GetRootAgentCount() == 0) { //If the region is empty, this change has been made by an automated process -- cgit v1.1 From e642b80a79bc2a5585972caa14a8f5f59a5dc6fb Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 2 Nov 2012 17:49:54 +0000 Subject: actually remove the use of random on persist timmings --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 6339522..e94ecee 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -148,13 +148,13 @@ namespace OpenSim.Region.Framework.Scenes m_rand = new Random(BitConverter.ToInt32(val, 0)); } */ - Random m_rand = new Random(); if (m_scene.GetRootAgentCount() == 0) { //If the region is empty, this change has been made by an automated process //and thus we delay the persist time by a random amount between 1.5 and 2.5. - float factor = 1.5f + (float)(m_rand.NextDouble()); +// float factor = 1.5f + (float)(m_rand.NextDouble()); + float factor = 2.0f; m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor); m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor); } @@ -162,8 +162,10 @@ namespace OpenSim.Region.Framework.Scenes { //If the region is not empty, we want to obey the minimum and maximum persist times //but add a random factor so we stagger the object persistance a little - m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5 - m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0 +// m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5 +// m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0 + m_maxPersistTime = m_scene.m_persistAfter; + m_minPersistTime = m_scene.m_dontPersistBefore; } } } -- cgit v1.1 From 1090ff727851b0ee571a0d99e232a81b95f2bdef Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 4 Nov 2012 14:57:27 +0000 Subject: removed potencial null refs and rearrange code a bit --- .../PrimLimitsModule/PrimLimitsModule.cs | 32 +++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs index 59ff9b8..39cabb5 100644 --- a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs +++ b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs @@ -121,34 +121,40 @@ namespace OpenSim.Region.OptionalModules private bool CanObjectEnter(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene) { - if ((newPoint.X > 257f || newPoint.X < -1f || newPoint.Y > 257f || newPoint.Y < -1f)) + if (newPoint.X < -1f || newPoint.X > (float)(Constants.RegionSize + 1) || + newPoint.Y < -1f || newPoint.Y > (float)(Constants.RegionSize + 1)) return true; SceneObjectPart obj = scene.GetSceneObjectPart(objectID); - Vector3 oldPoint = obj.GroupPosition; - int objectCount = obj.ParentGroup.PrimCount; - ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y); + + if (obj == null) + return false; + + // Prim counts are determined by the location of the root prim. if we're + // moving a child prim, just let it pass + if (!obj.IsRoot) + { + return true; + } + ILandObject newParcel = scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); if (newParcel == null) return true; - int usedPrims = newParcel.PrimCounts.Total; - int simulatorCapacity = newParcel.GetSimulatorMaxPrimCount(); + Vector3 oldPoint = obj.GroupPosition; + ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y); // The prim hasn't crossed a region boundry so we don't need to worry // about prim counts here - if(oldParcel.Equals(newParcel)) + if(oldParcel != null && oldParcel.Equals(newParcel)) { return true; } - // Prim counts are determined by the location of the root prim. if we're - // moving a child prim, just let it pass - if(!obj.IsRoot) - { - return true; - } + int objectCount = obj.ParentGroup.PrimCount; + int usedPrims = newParcel.PrimCounts.Total; + int simulatorCapacity = newParcel.GetSimulatorMaxPrimCount(); // TODO: Add Special Case here for temporary prims -- cgit v1.1 From 4fa088bafb4c78ad3177b0e944a4312bd6abdea7 Mon Sep 17 00:00:00 2001 From: teravus Date: Sun, 4 Nov 2012 22:57:24 -0500 Subject: Pipe Throttle Update Event to EventManager, client --> ScenePresence --> EventManager, so that modules can know when throttles are updated. The event contains no client specific data to preserve the possibility of 'multiple clients' and you must still call ControllingClient.GetThrottlesPacked(f) to see what the throttles actually are once the event fires. Hook EventManager.OnUpdateThrottle to GetTextureModule. --- OpenSim/Framework/IClientAPI.cs | 2 +- .../ClientStack/Linden/Caps/GetTextureModule.cs | 42 ++++++++++++++++++++++ .../Region/ClientStack/Linden/UDP/LLClientView.cs | 11 ++++++ OpenSim/Region/Framework/Scenes/EventManager.cs | 13 +++++++ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 +++ .../Server/IRCClientView.cs | 1 + .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 2 +- OpenSim/Tests/Common/Mock/TestClient.cs | 2 +- 8 files changed, 75 insertions(+), 3 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 5909ce1..e31c7f6 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1038,7 +1038,7 @@ namespace OpenSim.Framework event MuteListEntryRemove OnRemoveMuteListEntry; event GodlikeMessage onGodlikeMessage; event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; - + event GenericCall2 OnUpdateThrottles; /// /// Set the debug level at which packet output should be printed to console. /// diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs index d1a1583..19d4b91 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs @@ -91,6 +91,7 @@ namespace OpenSim.Region.ClientStack.Linden { m_scene.EventManager.OnRegisterCaps -= RegisterCaps; m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; + m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate; m_scene = null; } @@ -101,6 +102,7 @@ namespace OpenSim.Region.ClientStack.Linden m_scene.EventManager.OnRegisterCaps += RegisterCaps; m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; + m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate; if (m_workerThreads == null) { @@ -118,6 +120,46 @@ namespace OpenSim.Region.ClientStack.Linden } } } + private int ExtractImageThrottle(byte[] pthrottles) + { + + byte[] adjData; + int pos = 0; + + if (!BitConverter.IsLittleEndian) + { + byte[] newData = new byte[7 * 4]; + Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4); + + for (int i = 0; i < 7; i++) + Array.Reverse(newData, i * 4, 4); + + adjData = newData; + } + else + { + adjData = pthrottles; + } + + // 0.125f converts from bits to bytes + //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + pos = pos + 16; + int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + return texture; + } + + // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent. + public void ThrottleUpdate(ScenePresence p) + { + byte[] throttles = p.ControllingClient.GetThrottlesPacked(1); + UUID user = p.UUID; + int imagethrottle = ExtractImageThrottle(throttles); + } public void PostInitialise() { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ee28914..ae9ed7f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -295,6 +295,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event MuteListEntryRemove OnRemoveMuteListEntry; public event GodlikeMessage onGodlikeMessage; public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; + public event GenericCall2 OnUpdateThrottles; #endregion Events @@ -6729,6 +6730,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion m_udpClient.SetThrottles(atpack.Throttle.Throttles); + GenericCall2 handler = OnUpdateThrottles; + if (handler != null) + { + handler(); + } return true; } @@ -11870,6 +11876,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SetChildAgentThrottle(byte[] throttles) { m_udpClient.SetThrottles(throttles); + GenericCall2 handler = OnUpdateThrottles; + if (handler != null) + { + handler(); + } } /// diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 7916c42..4a19c3b 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -376,6 +376,10 @@ namespace OpenSim.Region.Framework.Scenes public event ParcelPrimCountTainted OnParcelPrimCountTainted; public event GetScriptRunning OnGetScriptRunning; + public delegate void ThrottleUpdate(ScenePresence scenePresence); + + public event ThrottleUpdate OnThrottleUpdate; + /// /// RegisterCapsEvent is called by Scene after the Caps object /// has been instantiated and before it is return to the @@ -2641,5 +2645,14 @@ namespace OpenSim.Region.Framework.Scenes } } } + + public void TriggerThrottleUpdate(ScenePresence scenePresence) + { + ThrottleUpdate handler = OnThrottleUpdate; + if (handler != null) + { + handler(scenePresence); + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index a8aa551..2b9665c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -793,6 +793,7 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.OnChangeAnim += avnHandleChangeAnim; ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; ControllingClient.OnAutoPilotGo += MoveToTarget; + ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles; // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); @@ -3166,6 +3167,10 @@ namespace OpenSim.Region.Framework.Scenes } private static Vector3 marker = new Vector3(-1f, -1f, -1f); + private void RaiseUpdateThrottles() + { + m_scene.EventManager.TriggerThrottleUpdate(this); + } /// /// This updates important decision making data about a child agent /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index a484300..28b8293 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -873,6 +873,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public event MuteListEntryRemove OnRemoveMuteListEntry; public event GodlikeMessage onGodlikeMessage; public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; + public event GenericCall2 OnUpdateThrottles; #pragma warning restore 67 diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 7c693b6..6c8e2fc 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -473,7 +473,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC public event MuteListEntryRemove OnRemoveMuteListEntry; public event GodlikeMessage onGodlikeMessage; public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; - + public event GenericCall2 OnUpdateThrottles; #pragma warning restore 67 #endregion diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 49a8d26..78bb18e 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -320,7 +320,7 @@ namespace OpenSim.Tests.Common.Mock public event MuteListEntryRemove OnRemoveMuteListEntry; public event GodlikeMessage onGodlikeMessage; public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; - + public event GenericCall2 OnUpdateThrottles; #pragma warning restore 67 /// -- cgit v1.1 From b7b96a5e4f1e26341742e35e5253e6e14797bd15 Mon Sep 17 00:00:00 2001 From: teravus Date: Mon, 5 Nov 2012 13:10:00 -0500 Subject: Another step in the chain. Pipe the throttle update to the appropriate PollServiceTextureEventArgs. Each poll service having it's own throttle member is more consistent with the model then the region module keeping track of all of them globally and better for locking too. The Poll Services object is not set static to handle multiple nearby regions on the same simulator. Next step is hooking it up to HasEvents --- .../Handlers/GetTexture/GetTextureHandler.cs | 6 ++- .../ClientStack/Linden/Caps/GetTextureModule.cs | 47 ++++++++++++++++------ 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs index b3a4d61..86e7aa0 100644 --- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs @@ -68,7 +68,7 @@ namespace OpenSim.Capabilities.Handlers ret["content_type"] = "text/plain"; ret["keepalive"] = false; ret["reusecontext"] = false; - + ret["int_bytes"] = 0; string textureStr = (string)request["texture_id"]; string format = (string)request["format"]; @@ -223,6 +223,7 @@ namespace OpenSim.Capabilities.Handlers { response["int_response_code"] = (int)System.Net.HttpStatusCode.OK; response["bin_response_data"] = texture.Data; + response["int_bytes"] = texture.Data.Length; } else { @@ -232,6 +233,7 @@ namespace OpenSim.Capabilities.Handlers byte[] d = new byte[len]; Array.Copy(texture.Data, start, d, 0, len); response["bin_response_data"] = d; + response["int_bytes"] = len; } // response.Body.Write(texture.Data, start, len); } @@ -252,6 +254,8 @@ namespace OpenSim.Capabilities.Handlers response["content_type"] = "image/" + format; response["bin_response_data"] = texture.Data; + response["int_bytes"] = texture.Data.Length; + // response.Body.Write(texture.Data, 0, texture.Data.Length); } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs index 19d4b91..4bfdbff 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs @@ -61,6 +61,13 @@ namespace OpenSim.Region.ClientStack.Linden public Hashtable request; } + public struct aPollResponse + { + public Hashtable response; + public int bytes; + } + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; @@ -75,6 +82,8 @@ namespace OpenSim.Region.ClientStack.Linden private static OpenMetaverse.BlockingQueue m_queue = new OpenMetaverse.BlockingQueue(); + private Dictionary m_pollservices = new Dictionary(); + #region ISharedRegionModule Members public void Initialise(IConfigSource source) @@ -147,7 +156,7 @@ namespace OpenSim.Region.ClientStack.Linden // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; - pos = pos + 16; + pos = pos + 20; int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); return texture; @@ -159,6 +168,11 @@ namespace OpenSim.Region.ClientStack.Linden byte[] throttles = p.ControllingClient.GetThrottlesPacked(1); UUID user = p.UUID; int imagethrottle = ExtractImageThrottle(throttles); + PollServiceTextureEventArgs args; + if (m_pollservices.TryGetValue(user,out args)) + { + args.UpdateThrottle(imagethrottle); + } } public void PostInitialise() @@ -187,8 +201,8 @@ namespace OpenSim.Region.ClientStack.Linden { private List requests = new List(); - private Dictionary responses = - new Dictionary(); + private Dictionary responses = + new Dictionary(); private Scene m_scene; @@ -196,7 +210,7 @@ namespace OpenSim.Region.ClientStack.Linden base(null, null, null, null, pId, int.MaxValue) { m_scene = scene; - + // x is request id, y is userid HasEvents = (x, y) => { lock (responses) @@ -208,7 +222,7 @@ namespace OpenSim.Region.ClientStack.Linden { try { - return responses[x]; + return responses[x].response; } finally { @@ -216,14 +230,14 @@ namespace OpenSim.Region.ClientStack.Linden } } }; - + // x is request id, y is request data hashtable Request = (x, y) => { aPollRequest reqinfo = new aPollRequest(); reqinfo.thepoll = this; reqinfo.reqID = x; reqinfo.request = y; - + m_queue.Enqueue(reqinfo); }; @@ -265,16 +279,21 @@ namespace OpenSim.Region.ClientStack.Linden response["content_type"] = "text/plain"; response["keepalive"] = false; response["reusecontext"] = false; - + lock (responses) - responses[requestID] = response; + responses[requestID] = new aPollResponse() {bytes = 0,response = response}; return; } response = m_getTextureHandler.Handle(requestinfo.request); lock (responses) - responses[requestID] = response; + responses[requestID] = new aPollResponse() { bytes = (int)response["int_bytes"], response = response}; + } + + internal void UpdateThrottle(int pimagethrottle) + { + } } @@ -299,19 +318,23 @@ namespace OpenSim.Region.ClientStack.Linden protocol = "https"; } caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); - + m_pollservices.Add(agentID, args); m_capsDict[agentID] = capUrl; } private void DeregisterCaps(UUID agentID, Caps caps) { string capUrl; - + PollServiceTextureEventArgs args; if (m_capsDict.TryGetValue(agentID, out capUrl)) { MainServer.Instance.RemoveHTTPHandler("", capUrl); m_capsDict.Remove(agentID); } + if (m_pollservices.TryGetValue(agentID, out args)) + { + m_pollservices.Remove(agentID); + } } private void DoTextureRequests() -- cgit v1.1 From 182b4872437e97762ac494dbf1815fe63aa29405 Mon Sep 17 00:00:00 2001 From: teravus Date: Mon, 5 Nov 2012 22:05:10 -0500 Subject: This implements the Caps throttler. After some testing, the system seemed to be OK with me specifying allowing 1 oversized image per 70,000b/sec with at least one. Try it out, start with a low bandwidth setting and then, set your bandwidth setting middle/high and see the difference. Tested with Two Clients on a region with 1800 textures all visible at once. --- .../ClientStack/Linden/Caps/GetTextureModule.cs | 119 ++++++++++++++++++--- 1 file changed, 106 insertions(+), 13 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs index 4bfdbff..8cba6c8 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs @@ -61,7 +61,7 @@ namespace OpenSim.Region.ClientStack.Linden public Hashtable request; } - public struct aPollResponse + public class aPollResponse { public Hashtable response; public int bytes; @@ -151,13 +151,18 @@ namespace OpenSim.Region.ClientStack.Linden } // 0.125f converts from bits to bytes - //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; - // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; - // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; - // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; - // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + //pos += 4; + // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + //pos += 4; + // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + // pos += 4; + // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + // pos += 4; + // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); + // pos += 4; pos = pos + 20; - int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; + int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4; //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); return texture; } @@ -205,7 +210,7 @@ namespace OpenSim.Region.ClientStack.Linden new Dictionary(); private Scene m_scene; - + private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000); public PollServiceTextureEventArgs(UUID pId, Scene scene) : base(null, null, null, null, pId, int.MaxValue) { @@ -214,7 +219,12 @@ namespace OpenSim.Region.ClientStack.Linden HasEvents = (x, y) => { lock (responses) - return responses.ContainsKey(x); + { + bool ret = m_throttler.hasEvents(x, responses); + m_throttler.ProcessTime(); + return ret; + + } }; GetEvents = (x, y) => { @@ -281,19 +291,27 @@ namespace OpenSim.Region.ClientStack.Linden response["reusecontext"] = false; lock (responses) - responses[requestID] = new aPollResponse() {bytes = 0,response = response}; + responses[requestID] = new aPollResponse() {bytes = 0, response = response}; return; } - + response = m_getTextureHandler.Handle(requestinfo.request); lock (responses) - responses[requestID] = new aPollResponse() { bytes = (int)response["int_bytes"], response = response}; + { + responses[requestID] = new aPollResponse() + { + bytes = (int) response["int_bytes"], + response = response + }; + + } + m_throttler.ProcessTime(); } internal void UpdateThrottle(int pimagethrottle) { - + m_throttler.ThrottleBytes = pimagethrottle; } } @@ -347,4 +365,79 @@ namespace OpenSim.Region.ClientStack.Linden } } } + + internal sealed class CapsDataThrottler + { + + private volatile int currenttime = 0; + private volatile int lastTimeElapsed = 0; + private volatile int BytesSent = 0; + private int oversizedImages = 0; + public CapsDataThrottler(int pBytes, int max, int min) + { + ThrottleBytes = pBytes; + lastTimeElapsed = Util.EnvironmentTickCount(); + } + public bool hasEvents(UUID key, Dictionary responses) + { + PassTime(); + // Note, this is called IN LOCK + bool haskey = responses.ContainsKey(key); + if (!haskey) + { + return false; + } + GetTextureModule.aPollResponse response; + if (responses.TryGetValue(key,out response)) + { + + // Normal + if (BytesSent + response.bytes <= ThrottleBytes) + { + BytesSent += response.bytes; + //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false }; + //m_actions.Add(timeBasedAction); + return true; + } + // Big textures + else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes%50000) + 1)) + { + Interlocked.Increment(ref oversizedImages); + BytesSent += response.bytes; + //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false }; + //m_actions.Add(timeBasedAction); + return true; + } + else + { + return false; + } + } + + return haskey; + } + public void ProcessTime() + { + PassTime(); + } + + + private void PassTime() + { + currenttime = Util.EnvironmentTickCount(); + int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed); + //processTimeBasedActions(responses); + if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000) + { + lastTimeElapsed = Util.EnvironmentTickCount(); + BytesSent -= ThrottleBytes; + if (BytesSent < 0) BytesSent = 0; + if (BytesSent < ThrottleBytes) + { + oversizedImages = 0; + } + } + } + public int ThrottleBytes; + } } -- cgit v1.1 From 6faa7fc7f9c47ed4a15a1fdf9a93efab0f163e74 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 17 Nov 2012 02:31:56 +0100 Subject: Prevent a buffer overflow in asset receiving --- .../Agent/AssetTransaction/AssetXferUploader.cs | 31 ++++++++++++++-------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index 4cedfe6..4b54843 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -100,18 +100,27 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (XferID == xferID) { - if (m_asset.Data.Length > 1) - { - byte[] destinationArray = new byte[m_asset.Data.Length + data.Length]; - Array.Copy(m_asset.Data, 0, destinationArray, 0, m_asset.Data.Length); - Array.Copy(data, 0, destinationArray, m_asset.Data.Length, data.Length); - m_asset.Data = destinationArray; - } - else + lock (this) { - byte[] buffer2 = new byte[data.Length - 4]; - Array.Copy(data, 4, buffer2, 0, data.Length - 4); - m_asset.Data = buffer2; + int assetLength = m_asset.Data.Length; + int dataLength = data.Length; + + if (m_asset.Data.Length > 1) + { + byte[] destinationArray = new byte[assetLength + dataLength]; + Array.Copy(m_asset.Data, 0, destinationArray, 0, assetLength); + Array.Copy(data, 0, destinationArray, assetLength, dataLength); + m_asset.Data = destinationArray; + } + else + { + if (dataLength > 4) + { + byte[] buffer2 = new byte[dataLength - 4]; + Array.Copy(data, 4, buffer2, 0, dataLength - 4); + m_asset.Data = buffer2; + } + } } ourClient.SendConfirmXfer(xferID, packetID); -- cgit v1.1