diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs index 35fa5ed76f..2f5ea23056 100644 --- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs @@ -241,44 +241,52 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload { ITextureSender sender = null; - try - { +// try +// { while (true) { - sender = m_queueSenders.Dequeue(); - - if (sender.Cancel) + try { - TextureSent(sender); + sender = m_queueSenders.Dequeue(); - sender.Cancel = false; - } - else - { - bool finished = sender.SendTexturePacket(); - if (finished) + if (sender.Cancel) { TextureSent(sender); + + sender.Cancel = false; } else { - m_queueSenders.Enqueue(sender); + bool finished = sender.SendTexturePacket(); + if (finished) + { + TextureSent(sender); + } + else + { + m_queueSenders.Enqueue(sender); + } } + + // Make sure that any sender we currently have can get garbage collected + sender = null; + + //m_log.InfoFormat("[TEXTURE] Texture sender queue size: {0}", m_queueSenders.Count()); + } + catch(Exception e) + { + m_log.ErrorFormat( + "[TEXTURE]: Texture send thread caught exception. The texture send was aborted. Exception is {0}", e); } - - // Make sure that any sender we currently have can get garbage collected - sender = null; - - //m_log.InfoFormat("[TEXTURE] Texture sender queue size: {0}", m_queueSenders.Count()); } - } - catch (Exception e) - { - // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened - m_log.ErrorFormat( - "[TEXTURE]: Texture send thread terminating with exception. PLEASE REBOOT YOUR SIM - TEXTURES WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}", - e); - } +// } +// catch (Exception e) +// { +// // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened +// m_log.ErrorFormat( +// "[TEXTURE]: Texture send thread terminating with exception. PLEASE REBOOT YOUR SIM - TEXTURES WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}", +// e); +// } } /// diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs index c06406470f..044ee765c9 100644 --- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs @@ -28,7 +28,6 @@ using System.Reflection; using log4net; using OpenMetaverse; -using OpenMetaverse.Packets; using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs index d6c9877019..aab4ad0cb5 100644 --- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs @@ -56,11 +56,10 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload /// /// We will allow the client to request the same texture n times before dropping further requests /// - /// This number includes repeated requests for the same texture at different resolutions (which we don't - /// currently handle properly as far as I know). However, this situation should be handled in a more - /// sophisticated way. + /// This number contains repeated requests for the same texture at different resolutions (which + /// are handled since r7368). However, this situation should be handled in a more sophisticated way. /// - private static readonly int MAX_ALLOWED_TEXTURE_REQUESTS = 5; + private static readonly int MAX_ALLOWED_TEXTURE_REQUESTS = 15; /// /// XXX Also going to limit requests for found textures. @@ -149,7 +148,7 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload m_scene.AddPendingDownloads(1); - TextureSender.TextureSender requestHandler = new TextureSender.TextureSender(m_client, e.DiscardLevel, e.PacketNumber); + TextureSender.TextureSender requestHandler = new TextureSender.TextureSender(m_client, e.DiscardLevel, e.PacketNumber, e.Priority); m_textureSenders.Add(e.RequestedAssetID, requestHandler); m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true); diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs b/OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs index 4049dfcb1c..cff215b278 100644 --- a/OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs @@ -53,7 +53,7 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureSender agent.startpos = Vector3.Zero; agent.CapsPath = "http://wibble.com"; - new TextureSender(new TestClient(agent), 0, 0); + new TextureSender(new TestClient(agent), 0, 0, 1.0f); } } } \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs b/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs index 57129dd92f..0e34271daa 100644 --- a/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs @@ -27,13 +27,104 @@ using System; using System.Reflection; -using OpenMetaverse.Packets; using log4net; using OpenSim.Framework; using OpenSim.Region.Environment.Interfaces; namespace OpenSim.Region.Environment.Modules.Agent.TextureSender { + public class ImageDownload + { + public const int FIRST_IMAGE_PACKET_SIZE = 600; + public const int IMAGE_PACKET_SIZE = 1000; + + public OpenMetaverse.AssetTexture Texture; + public int DiscardLevel; + public float Priority; + public int CurrentPacket; + public int StopPacket; + + public ImageDownload(OpenMetaverse.AssetTexture texture, int discardLevel, float priority, int packet) + { + Texture = texture; + Update(discardLevel, priority, packet); + } + + /// + /// Updates an image transfer with new information and recalculates + /// offsets + /// + /// New requested discard level + /// New requested priority + /// New requested packet offset + public void Update(int discardLevel, float priority, int packet) + { + Priority = priority; + DiscardLevel = Clamp(discardLevel, 0, Texture.LayerInfo.Length - 1); + StopPacket = GetPacketForBytePosition(Texture.LayerInfo[(Texture.LayerInfo.Length - 1) - DiscardLevel].End); + CurrentPacket = Clamp(packet, 1, TexturePacketCount()); + } + + /// + /// Returns the total number of packets needed to transfer this texture, + /// including the first packet of size FIRST_IMAGE_PACKET_SIZE + /// + /// Total number of packets needed to transfer this texture + public int TexturePacketCount() + { + return ((Texture.AssetData.Length - FIRST_IMAGE_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE) + 1; + } + + /// + /// Returns the current byte offset for this transfer, calculated from + /// the CurrentPacket + /// + /// Current byte offset for this transfer + public int CurrentBytePosition() + { + return FIRST_IMAGE_PACKET_SIZE + (CurrentPacket - 1) * IMAGE_PACKET_SIZE; + } + + /// + /// Returns the size, in bytes, of the last packet. This will be somewhere + /// between 1 and IMAGE_PACKET_SIZE bytes + /// + /// Size of the last packet in the transfer + public int LastPacketSize() + { + return Texture.AssetData.Length - (FIRST_IMAGE_PACKET_SIZE + ((TexturePacketCount() - 2) * IMAGE_PACKET_SIZE)); + } + + /// + /// Find the packet number that contains a given byte position + /// + /// Byte position + /// Packet number that contains the given byte position + int GetPacketForBytePosition(int bytePosition) + { + return ((bytePosition - FIRST_IMAGE_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE); + } + + /// + /// Clamp a given value between a range + /// + /// Value to clamp + /// Minimum allowable value + /// Maximum allowable value + /// A value inclusively between lower and upper + static int Clamp(int value, int min, int max) + { + // First we check to see if we're greater than the max + value = (value > max) ? max : value; + + // Then we check to see if we're less than the min. + value = (value < min) ? min : value; + + // There's no check to see if min > max. + return value; + } + } + /// /// A TextureSender handles the process of receiving a texture requested by the client from the /// AssetCache, and then sending that texture back to the client. @@ -43,90 +134,81 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureSender private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - /// - /// Records the number of times texture send has been called. - /// - public int counter = 0; - public bool ImageLoaded = false; /// /// Holds the texture asset to send. /// private AssetBase m_asset; + private bool m_cancel = false; + private bool m_sending = false; + private bool sendFirstPacket = false; + private int initialDiscardLevel = 0; + private int initialPacketNum = 0; + private float initialPriority = 0.0f; - //public UUID assetID { get { return m_asset.FullID; } } - - // private bool m_cancel = false; - - // See ITextureSender - - // private bool m_sending = false; - - /// - /// This is actually the number of extra packets required to send the texture data! We always assume - /// at least one is required. - /// - private int NumPackets = 0; - - /// - /// Holds the packet number to send next. In this case, each packet is 1000 bytes long and starts - /// at the 600th byte (0th indexed). - /// - private int PacketCounter = 0; - - private int RequestedDiscardLevel = -1; + private ImageDownload download; private IClientAPI RequestUser; - private uint StartPacketNumber = 0; - public TextureSender(IClientAPI client, int discardLevel, uint packetNumber) + public TextureSender(IClientAPI client, int discardLevel, uint packetNumber, float priority) { RequestUser = client; - RequestedDiscardLevel = discardLevel; - StartPacketNumber = packetNumber; + initialDiscardLevel = discardLevel; + initialPacketNum = (int)packetNumber; + initialPriority = priority; } #region ITextureSender Members public bool Cancel { - get { return false; } - set - { - // m_cancel = value; - } + get { return m_cancel; } + set { m_cancel = value; } } public bool Sending { - get { return false; } - set - { - // m_sending = value; - } + get { return m_sending; } + set { m_sending = value; } } // See ITextureSender public void UpdateRequest(int discardLevel, uint packetNumber) { - RequestedDiscardLevel = discardLevel; - StartPacketNumber = packetNumber; - PacketCounter = (int) StartPacketNumber; + if (download == null) + return; + + lock (download) + { + if (discardLevel < download.DiscardLevel) + m_log.DebugFormat("Image download {0} is changing from DiscardLevel {1} to {2}", + m_asset.FullID, download.DiscardLevel, discardLevel); + + if (packetNumber != download.CurrentPacket) + m_log.DebugFormat("Image download {0} is changing from Packet {1} to {2}", + m_asset.FullID, download.CurrentPacket, packetNumber); + + download.Update(discardLevel, download.Priority, (int)packetNumber); + + sendFirstPacket = true; + } } // See ITextureSender public bool SendTexturePacket() { - //m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.FullID); - - SendPacket(); - counter++; - if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) || - ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets / (RequestedDiscardLevel + 1))))) + if (download != null && !m_cancel && (sendFirstPacket || download.CurrentPacket <= download.StopPacket)) { + SendPacket(); + return false; + } + else + { + m_sending = false; + m_cancel = true; + sendFirstPacket = false; return true; } - return false; } #endregion @@ -138,9 +220,52 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureSender public void TextureReceived(AssetBase asset) { m_asset = asset; - NumPackets = CalculateNumPackets(asset.Data.Length); - PacketCounter = (int) StartPacketNumber; - ImageLoaded = true; + + try + { + OpenMetaverse.AssetTexture texture = new OpenMetaverse.AssetTexture(m_asset.FullID, m_asset.Data); + if (texture.DecodeLayerBoundaries()) + { + bool sane = true; + + // Sanity check all of the layers + for (int i = 0; i < texture.LayerInfo.Length; i++) + { + if (texture.LayerInfo[i].End > texture.AssetData.Length) + { + sane = false; + break; + } + } + + if (sane) + { + download = new ImageDownload(texture, initialDiscardLevel, initialPriority, initialPacketNum); + ImageLoaded = true; + m_sending = true; + m_cancel = false; + sendFirstPacket = true; + return; + } + else + { + m_log.Error("JPEG2000 texture decoding succeeded, but sanity check failed for " + + m_asset.FullID.ToString()); + } + } + else + { + m_log.Error("JPEG2000 texture decoding failed for " + m_asset.FullID.ToString()); + } + } + catch (Exception ex) + { + m_log.Error("JPEG2000 texture decoding threw an exception for " + m_asset.FullID.ToString(), ex); + } + + ImageLoaded = false; + m_sending = false; + m_cancel = true; } /// @@ -148,66 +273,48 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureSender /// private void SendPacket() { - if (PacketCounter <= NumPackets) + lock (download) { - if (PacketCounter == 0) + if (sendFirstPacket) { - if (NumPackets == 0) + sendFirstPacket = false; + + if (m_asset.Data.Length <= ImageDownload.FIRST_IMAGE_PACKET_SIZE) { RequestUser.SendImageFirstPart(1, m_asset.FullID, (uint)m_asset.Data.Length, m_asset.Data, 2); - PacketCounter++; + return; } else { - byte[] ImageData1 = new byte[600]; - Array.Copy(m_asset.Data, 0, ImageData1, 0, 600); - - RequestUser.SendImageFirstPart( - (ushort)(NumPackets), m_asset.FullID, (uint)m_asset.Data.Length, ImageData1, 2); - PacketCounter++; + byte[] firstImageData = new byte[ImageDownload.FIRST_IMAGE_PACKET_SIZE]; + try { Buffer.BlockCopy(m_asset.Data, 0, firstImageData, 0, ImageDownload.FIRST_IMAGE_PACKET_SIZE); } + catch (Exception) + { + m_log.Error("Texture data copy failed on first packet for " + m_asset.FullID.ToString()); + m_cancel = true; + m_sending = false; + return; + } + RequestUser.SendImageFirstPart((ushort)download.TexturePacketCount(), m_asset.FullID, (uint)m_asset.Data.Length, firstImageData, 2); } } - else + + int imagePacketSize = (download.CurrentPacket == download.TexturePacketCount() - 1) ? + download.LastPacketSize() : ImageDownload.IMAGE_PACKET_SIZE; + + byte[] imageData = new byte[imagePacketSize]; + try { Buffer.BlockCopy(m_asset.Data, download.CurrentBytePosition(), imageData, 0, imagePacketSize); } + catch (Exception) { - int size = m_asset.Data.Length - 600 - (1000 * (PacketCounter - 1)); - if (size > 1000) size = 1000; - byte[] imageData = new byte[size]; - try - { - Array.Copy(m_asset.Data, 600 + (1000 * (PacketCounter - 1)), imageData, 0, size); - } - catch (ArgumentOutOfRangeException) - { - m_log.Error("[TEXTURE SENDER]: Unable to separate texture into multiple packets: Array bounds failure on asset:" + - m_asset.FullID.ToString()); - return; - } - - RequestUser.SendImageNextPart((ushort)PacketCounter, m_asset.FullID, imageData); - PacketCounter++; + m_log.Error("Texture data copy failed for " + m_asset.FullID.ToString()); + m_cancel = true; + m_sending = false; + return; } + + RequestUser.SendImageNextPart((ushort)download.CurrentPacket, m_asset.FullID, imageData); + ++download.CurrentPacket; } } - - /// - /// Calculate the number of packets that will be required to send the texture loaded into this sender - /// This is actually the number of 1000 byte packets not including an initial 600 byte packet... - /// - /// - /// - private int CalculateNumPackets(int length) - { - int numPackets = 0; - - if (length > 600) - { - //over 600 bytes so split up file - int restData = (length - 600); - int restPackets = ((restData + 999) / 1000); - numPackets = restPackets; - } - - return numPackets; - } } } diff --git a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs index 580982df8e..ed77b2e952 100644 --- a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs @@ -30,7 +30,6 @@ using System.Collections; using System.Collections.Generic; using System.Reflection; using OpenMetaverse; -using OpenMetaverse.Packets; using log4net; using Nini.Config; using Nwc.XmlRpc; diff --git a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs index 1e26c913c1..bcc0d19b3a 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs @@ -31,7 +31,6 @@ using System.Reflection; using System.Text; using System.Timers; using OpenMetaverse; -using OpenMetaverse.Packets; using log4net; using OpenSim.Framework; using OpenSim.Framework.Communications.Cache; diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 340dd39e29..343130976d 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -544,11 +544,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; Evidence evidence = new Evidence(baseEvidence); - m_AppDomains[appDomain] = + AppDomain sandbox = AppDomain.CreateDomain( m_Scene.RegionInfo.RegionID.ToString(), evidence, appSetup); + PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); + AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); + PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); + PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); + CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); + sandboxPolicy.RootCodeGroup = sandboxCodeGroup; + sandbox.SetAppDomainPolicy(sandboxPolicy); + + m_AppDomains[appDomain] = sandbox; + m_AppDomains[appDomain].AssemblyResolve += new ResolveEventHandler( AssemblyResolver.OnAssemblyResolve); diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll index be1cd40d7b..be1c6c2f09 100644 Binary files a/bin/OpenMetaverse.dll and b/bin/OpenMetaverse.dll differ diff --git a/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64.so b/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64.so index d8f4942e15..c2292fac41 100644 Binary files a/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64.so and b/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64.so differ diff --git a/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1.dylib b/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1.dylib index 0157dcf842..dc5077558d 100644 Binary files a/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1.dylib and b/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1.dylib differ diff --git a/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1.so b/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1.so index 9b19d8a070..53543e7b90 100644 Binary files a/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1.so and b/bin/libopenjpeg-dotnet-2.1.3.0-dotnet-1.so differ diff --git a/bin/openjpeg-dotnet.dll b/bin/openjpeg-dotnet.dll index d5f71c10ca..1cede1c499 100644 Binary files a/bin/openjpeg-dotnet.dll and b/bin/openjpeg-dotnet.dll differ