From a89d097355526d4dc52a75a9734c6a02c3008ef4 Mon Sep 17 00:00:00 2001 From: Dr Scofield Date: Mon, 9 Feb 2009 09:16:15 +0000 Subject: starting phase 2 of the OpenSim.Region.Environment commit: relocating OpenSim.Region.Environment.Modules.Agent en bloc to OpenSim.Region.CoreModules --- .../Agent/TextureSender/J2KDecoderModule.cs | 533 --------------------- .../TextureSender/Tests/TextureSenderTests.cs | 177 ------- .../Modules/Agent/TextureSender/TextureSender.cs | 213 -------- 3 files changed, 923 deletions(-) delete mode 100644 OpenSim/Region/Environment/Modules/Agent/TextureSender/J2KDecoderModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs delete mode 100644 OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs (limited to 'OpenSim/Region/Environment/Modules/Agent/TextureSender') diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/Environment/Modules/Agent/TextureSender/J2KDecoderModule.cs deleted file mode 100644 index 8524592..0000000 --- a/OpenSim/Region/Environment/Modules/Agent/TextureSender/J2KDecoderModule.cs +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.IO; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenMetaverse.Imaging; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Agent.TextureSender -{ - public class J2KDecoderModule : IRegionModule, IJ2KDecoder - { - #region IRegionModule Members - - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Cached Decoded Layers - /// - private readonly Dictionary m_cacheddecode = new Dictionary(); - private bool OpenJpegFail = false; - private readonly string CacheFolder = Util.dataDir() + "/j2kDecodeCache"; - private readonly J2KDecodeFileCache fCache; - - /// - /// List of client methods to notify of results of decode - /// - private readonly Dictionary> m_notifyList = new Dictionary>(); - - public J2KDecoderModule() - { - fCache = new J2KDecodeFileCache(CacheFolder); - } - - public void Initialise(Scene scene, IConfigSource source) - { - scene.RegisterModuleInterface(this); - } - - public void PostInitialise() - { - - } - - public void Close() - { - - } - - public string Name - { - get { return "J2KDecoderModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - #region IJ2KDecoder Members - - - public void decode(UUID AssetId, byte[] assetData, DecodedCallback decodedReturn) - { - // Dummy for if decoding fails. - OpenJPEG.J2KLayerInfo[] result = new OpenJPEG.J2KLayerInfo[0]; - - // Check if it's cached - bool cached = false; - lock (m_cacheddecode) - { - if (m_cacheddecode.ContainsKey(AssetId)) - { - cached = true; - result = m_cacheddecode[AssetId]; - } - } - - // If it's cached, return the cached results - if (cached) - { - decodedReturn(AssetId, result); - } - else - { - // not cached, so we need to decode it - // Add to notify list and start decoding. - // Next request for this asset while it's decoding will only be added to the notify list - // once this is decoded, requests will be served from the cache and all clients in the notifylist will be updated - bool decode = false; - lock (m_notifyList) - { - if (m_notifyList.ContainsKey(AssetId)) - { - m_notifyList[AssetId].Add(decodedReturn); - } - else - { - List notifylist = new List(); - notifylist.Add(decodedReturn); - m_notifyList.Add(AssetId, notifylist); - decode = true; - } - } - // Do Decode! - if (decode) - { - doJ2kDecode(AssetId, assetData); - } - } - } - - /// - /// Provides a synchronous decode so that caller can be assured that this executes before the next line - /// - /// - /// - public void syncdecode(UUID AssetId, byte[] j2kdata) - { - doJ2kDecode(AssetId, j2kdata); - } - - #endregion - - /// - /// Decode Jpeg2000 Asset Data - /// - /// UUID of Asset - /// Byte Array Asset Data - private void doJ2kDecode(UUID AssetId, byte[] j2kdata) - { - int DecodeTime = 0; - DecodeTime = System.Environment.TickCount; - OpenJPEG.J2KLayerInfo[] layers = new OpenJPEG.J2KLayerInfo[0]; // Dummy result for if it fails. Informs that there's only full quality - - if (!OpenJpegFail) - { - if (!fCache.TryLoadCacheForAsset(AssetId, out layers)) - { - try - { - - AssetTexture texture = new AssetTexture(AssetId, j2kdata); - 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) - { - layers = texture.LayerInfo; - fCache.SaveFileCacheForAsset(AssetId, layers); - - - // Write out decode time - m_log.InfoFormat("[J2KDecoderModule]: {0} Decode Time: {1}", System.Environment.TickCount - DecodeTime, - AssetId); - - } - else - { - m_log.WarnFormat( - "[J2KDecoderModule]: JPEG2000 texture decoding succeeded, but sanity check failed for {0}", - AssetId); - } - } - - else - { - m_log.WarnFormat("[J2KDecoderModule]: JPEG2000 texture decoding failed for {0}", AssetId); - } - texture = null; // dereference and dispose of ManagedImage - } - catch (DllNotFoundException) - { - m_log.Error( - "[J2KDecoderModule]: OpenJpeg is not installed properly. Decoding disabled! This will slow down texture performance! Often times this is because of an old version of GLIBC. You must have version 2.4 or above!"); - OpenJpegFail = true; - } - catch (Exception ex) - { - m_log.WarnFormat( - "[J2KDecoderModule]: JPEG2000 texture decoding threw an exception for {0}, {1}", - AssetId, ex); - } - } - - } - - - // Cache Decoded layers - lock (m_cacheddecode) - { - if (!m_cacheddecode.ContainsKey(AssetId)) - m_cacheddecode.Add(AssetId, layers); - - } - - - - // Notify Interested Parties - lock (m_notifyList) - { - if (m_notifyList.ContainsKey(AssetId)) - { - foreach (DecodedCallback d in m_notifyList[AssetId]) - { - if (d != null) - d.DynamicInvoke(AssetId, layers); - } - m_notifyList.Remove(AssetId); - } - } - } - } - - public class J2KDecodeFileCache - { - private readonly string m_cacheDecodeFolder; - private bool enabled = true; - - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Creates a new instance of a file cache - /// - /// base folder for the cache. Will be created if it doesn't exist - public J2KDecodeFileCache(string pFolder) - { - m_cacheDecodeFolder = pFolder; - if (!Directory.Exists(pFolder)) - { - Createj2KCacheFolder(pFolder); - } - - } - - /// - /// Save Layers to Disk Cache - /// - /// Asset to Save the layers. Used int he file name by default - /// The Layer Data from OpenJpeg - /// - public bool SaveFileCacheForAsset(UUID AssetId, OpenJPEG.J2KLayerInfo[] Layers) - { - if (Layers.Length > 0 && enabled) - { - FileStream fsCache = - new FileStream(String.Format("{0}/{1}", m_cacheDecodeFolder, FileNameFromAssetId(AssetId)), - FileMode.Create); - StreamWriter fsSWCache = new StreamWriter(fsCache); - StringBuilder stringResult = new StringBuilder(); - string strEnd = "\n"; - for (int i = 0; i < Layers.Length; i++) - { - if (i == (Layers.Length - 1)) - strEnd = ""; - - stringResult.AppendFormat("{0}|{1}|{2}{3}", Layers[i].Start, Layers[i].End, Layers[i].Size, strEnd); - } - fsSWCache.Write(stringResult.ToString()); - fsSWCache.Close(); - fsSWCache.Dispose(); - fsCache.Dispose(); - return true; - } - - - return false; - } - - - /// - /// Loads the Layer data from the disk cache - /// Returns true if load succeeded - /// - /// AssetId that we're checking the cache for - /// out layers to save to - /// true if load succeeded - public bool TryLoadCacheForAsset(UUID AssetId, out OpenJPEG.J2KLayerInfo[] Layers) - { - string filename = String.Format("{0}/{1}", m_cacheDecodeFolder, FileNameFromAssetId(AssetId)); - Layers = new OpenJPEG.J2KLayerInfo[0]; - - if (!File.Exists(filename)) - return false; - - if (!enabled) - { - return false; - } - - string readResult = string.Empty; - - try - { - FileStream fsCachefile = - new FileStream(filename, - FileMode.Open); - - StreamReader sr = new StreamReader(fsCachefile); - readResult = sr.ReadToEnd(); - - sr.Close(); - sr.Dispose(); - fsCachefile.Dispose(); - - } - catch (IOException ioe) - { - if (ioe is PathTooLongException) - { - m_log.Error( - "[J2KDecodeCache]: Cache Read failed. Path is too long."); - } - else if (ioe is DirectoryNotFoundException) - { - m_log.Error( - "[J2KDecodeCache]: Cache Read failed. Cache Directory does not exist!"); - enabled = false; - } - else - { - m_log.Error( - "[J2KDecodeCache]: Cache Read failed. IO Exception."); - } - return false; - - } - catch (UnauthorizedAccessException) - { - m_log.Error( - "[J2KDecodeCache]: Cache Read failed. UnauthorizedAccessException Exception. Do you have the proper permissions on this file?"); - return false; - } - catch (ArgumentException ae) - { - if (ae is ArgumentNullException) - { - m_log.Error( - "[J2KDecodeCache]: Cache Read failed. No Filename provided"); - } - else - { - m_log.Error( - "[J2KDecodeCache]: Cache Read failed. Filname was invalid"); - } - return false; - } - catch (NotSupportedException) - { - m_log.Error( - "[J2KDecodeCache]: Cache Read failed, not supported. Cache disabled!"); - enabled = false; - - return false; - } - catch (Exception e) - { - m_log.ErrorFormat( - "[J2KDecodeCache]: Cache Read failed, unknown exception. Error: {0}", - e.ToString()); - return false; - } - - string[] lines = readResult.Split('\n'); - - if (lines.Length <= 0) - return false; - - Layers = new OpenJPEG.J2KLayerInfo[lines.Length]; - - for (int i = 0; i < lines.Length; i++) - { - string[] elements = lines[i].Split('|'); - if (elements.Length == 3) - { - int element1, element2; - - try - { - element1 = Convert.ToInt32(elements[0]); - element2 = Convert.ToInt32(elements[1]); - } - catch (FormatException) - { - m_log.WarnFormat("[J2KDecodeCache]: Cache Read failed with ErrorConvert for {0}", AssetId); - Layers = new OpenJPEG.J2KLayerInfo[0]; - return false; - } - - Layers[i] = new OpenJPEG.J2KLayerInfo(); - Layers[i].Start = element1; - Layers[i].End = element2; - - } - else - { - // reading failed - m_log.WarnFormat("[J2KDecodeCache]: Cache Read failed for {0}", AssetId); - Layers = new OpenJPEG.J2KLayerInfo[0]; - return false; - } - } - - - - - return true; - } - - /// - /// Routine which converts assetid to file name - /// - /// asset id of the image - /// string filename - public string FileNameFromAssetId(UUID AssetId) - { - return String.Format("j2kCache_{0}.cache", AssetId); - } - - /// - /// Creates the Cache Folder - /// - /// Folder to Create - public void Createj2KCacheFolder(string pFolder) - { - try - { - Directory.CreateDirectory(pFolder); - } - catch (IOException ioe) - { - if (ioe is PathTooLongException) - { - m_log.Error( - "[J2KDecodeCache]: Cache Directory does not exist and create failed because the path to the cache folder is too long. Cache disabled!"); - } - else if (ioe is DirectoryNotFoundException) - { - m_log.Error( - "[J2KDecodeCache]: Cache Directory does not exist and create failed because the supplied base of the directory folder does not exist. Cache disabled!"); - } - else - { - m_log.Error( - "[J2KDecodeCache]: Cache Directory does not exist and create failed because of an IO Exception. Cache disabled!"); - } - enabled = false; - - } - catch (UnauthorizedAccessException) - { - m_log.Error( - "[J2KDecodeCache]: Cache Directory does not exist and create failed because of an UnauthorizedAccessException Exception. Cache disabled!"); - enabled = false; - } - catch (ArgumentException ae) - { - if (ae is ArgumentNullException) - { - m_log.Error( - "[J2KDecodeCache]: Cache Directory does not exist and create failed because the folder provided is invalid! Cache disabled!"); - } - else - { - m_log.Error( - "[J2KDecodeCache]: Cache Directory does not exist and create failed because no cache folder was provided! Cache disabled!"); - } - enabled = false; - } - catch (NotSupportedException) - { - m_log.Error( - "[J2KDecodeCache]: Cache Directory does not exist and create failed because it's not supported. Cache disabled!"); - enabled = false; - } - catch (Exception e) - { - m_log.ErrorFormat( - "[J2KDecodeCache]: Cache Directory does not exist and create failed because of an unknown exception. Cache disabled! Error: {0}", - e.ToString()); - enabled = false; - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs b/OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs deleted file mode 100644 index cfac868..0000000 --- a/OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using NUnit.Framework; -using NUnit.Framework.SyntaxHelpers; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Tests.Common.Mock; - -namespace OpenSim.Region.Environment.Modules.Agent.TextureSender -{ - [TestFixture] - public class UserTextureSenderTests - { - public UUID uuid1; - public UUID uuid2; - public UUID uuid3; - public UUID uuid4; - public int npackets, testsize; - public TestClient client; - public TextureSender ts; - public static Random random = new Random(); - - [TestFixtureSetUp] - public void Init() - { - AgentCircuitData agent = new AgentCircuitData(); - agent.AgentID = UUID.Random(); - agent.firstname = "testfirstname"; - agent.lastname = "testlastname"; - agent.SessionID = UUID.Zero; - agent.SecureSessionID = UUID.Zero; - agent.circuitcode = 123; - agent.BaseFolder = UUID.Zero; - agent.InventoryFolder = UUID.Zero; - agent.startpos = Vector3.Zero; - agent.CapsPath = "http://wibble.com"; - client = new TestClient(agent, null); - ts = new TextureSender(client, 0, 0); - testsize = random.Next(5000,15000); - npackets = CalculateNumPackets(testsize); - uuid1 = UUID.Random(); - uuid2 = UUID.Random(); - uuid3 = UUID.Random(); - uuid4 = UUID.Random(); - } - - /// - /// Test sending package - /// - [Test] - public void T010_SendPkg() - { - // Normal sending - AssetBase abase = new AssetBase(uuid1, "asset one"); - byte[] abdata = new byte[testsize]; - random.NextBytes(abdata); - abase.Data = abdata; - bool isdone = false; - ts.TextureReceived(abase); - for (int i = 0; i < npackets; i++) { - isdone = ts.SendTexturePacket(); - } - - Assert.That(isdone,Is.False); - isdone = ts.SendTexturePacket(); - Assert.That(isdone,Is.True); - } - - [Test] - public void T011_UpdateReq() - { - // Test packet number start - AssetBase abase = new AssetBase(uuid2, "asset two"); - byte[] abdata = new byte[testsize]; - random.NextBytes(abdata); - abase.Data = abdata; - - bool isdone = false; - ts.TextureReceived(abase); - ts.UpdateRequest(0,3); - - for (int i = 0; i < npackets-3; i++) { - isdone = ts.SendTexturePacket(); - } - - Assert.That(isdone,Is.False); - isdone = ts.SendTexturePacket(); - Assert.That(isdone,Is.True); - - // Test discard level - abase = new AssetBase(uuid3, "asset three"); - abdata = new byte[testsize]; - random.NextBytes(abdata); - abase.Data = abdata; - isdone = false; - ts.TextureReceived(abase); - ts.UpdateRequest(-1,0); - - Assert.That(ts.SendTexturePacket(),Is.True); - - abase = new AssetBase(uuid4, "asset four"); - abdata = new byte[testsize]; - random.NextBytes(abdata); - abase.Data = abdata; - isdone = false; - ts.TextureReceived(abase); - ts.UpdateRequest(0,5); - - for (int i = 0; i < npackets-5; i++) { - isdone = ts.SendTexturePacket(); - } - Assert.That(isdone,Is.False); - isdone = ts.SendTexturePacket(); - Assert.That(isdone,Is.True); - } - - [Test] - public void T999_FinishStatus() - { - // Of the 4 assets "sent", only 2 sent the first part. - Assert.That(client.sentdatapkt.Count,Is.EqualTo(2)); - - // Sum of all packets sent: - int totalpkts = (npackets) + (npackets - 2) + (npackets - 4); - Assert.That(client.sentpktpkt.Count,Is.EqualTo(totalpkts)); - } - - /// - /// 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... - /// Borrowed from TextureSender.cs - /// - /// - /// - 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/Agent/TextureSender/TextureSender.cs b/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs deleted file mode 100644 index 7d7efda..0000000 --- a/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using OpenMetaverse.Packets; -using log4net; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Agent.TextureSender -{ - /// - /// 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. - /// - public class TextureSender : ITextureSender - { - 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; - - //public UUID assetID { get { return m_asset.Metadata.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 IClientAPI RequestUser; - private uint StartPacketNumber = 0; - - public TextureSender(IClientAPI client, int discardLevel, uint packetNumber) - { - RequestUser = client; - RequestedDiscardLevel = discardLevel; - StartPacketNumber = packetNumber; - } - - #region ITextureSender Members - - public bool Cancel - { - get { return false; } - set - { - // m_cancel = value; - } - } - - public bool Sending - { - get { return false; } - set - { - // m_sending = value; - } - } - - // See ITextureSender - public void UpdateRequest(int discardLevel, uint packetNumber) - { - RequestedDiscardLevel = discardLevel; - StartPacketNumber = packetNumber; - PacketCounter = (int)StartPacketNumber; - } - - // See ITextureSender - public bool SendTexturePacket() - { - //m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.Metadata.FullID); - - SendPacket(); - counter++; - if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) || - ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets / (RequestedDiscardLevel + 1))))) - { - return true; - } - return false; - } - - #endregion - - /// - /// Load up the texture data to send. - /// - /// - public void TextureReceived(AssetBase asset) - { - m_asset = asset; - NumPackets = CalculateNumPackets(asset.Data.Length); - PacketCounter = (int)StartPacketNumber; - ImageLoaded = true; - } - - /// - /// Sends a texture packet to the client. - /// - private void SendPacket() - { - if (PacketCounter <= NumPackets) - { - if (PacketCounter == 0) - { - if (NumPackets == 0) - { - RequestUser.SendImageFirstPart(1, m_asset.Metadata.FullID, (uint)m_asset.Data.Length, m_asset.Data, 2); - PacketCounter++; - } - else - { - byte[] ImageData1 = new byte[600]; - Array.Copy(m_asset.Data, 0, ImageData1, 0, 600); - - RequestUser.SendImageFirstPart( - (ushort)(NumPackets), m_asset.Metadata.FullID, (uint)m_asset.Data.Length, ImageData1, 2); - PacketCounter++; - } - } - else - { - 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.Metadata.ID); - return; - } - - RequestUser.SendImageNextPart((ushort)PacketCounter, m_asset.Metadata.FullID, imageData); - PacketCounter++; - } - } - } - - /// - /// 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; - } - } -} -- cgit v1.1