diff --git a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs b/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs index 6d5d5e8568..4e96572f17 100644 --- a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs +++ b/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs @@ -132,6 +132,8 @@ namespace OpenSim.Region.Environment.Modules if (sender.Cancel) { TextureSent(sender); + + sender.Cancel = false; } else { @@ -152,219 +154,5 @@ namespace OpenSim.Region.Environment.Modules { sender.Sending = false; } - - public class UserTextureDownloadService - { - private readonly Dictionary m_textureSenders = new Dictionary(); - private readonly BlockingQueue m_sharedSendersQueue; - private readonly Scene m_scene; - - public UserTextureDownloadService(Scene scene, BlockingQueue sharedQueue) - { - m_scene = scene; - m_sharedSendersQueue = sharedQueue; - } - - public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e) - { - TextureSender textureSender; - - //TODO: should be working out the data size/ number of packets to be sent for each discard level - if ((e.DiscardLevel >= 0) || (e.Priority != 0)) - { - lock (m_textureSenders) - { - if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) - { - textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber); - textureSender.counter = 0; - - if ((textureSender.ImageLoaded) && - (textureSender.Sending == false)) - { - textureSender.Sending = true; - - if (!m_sharedSendersQueue.Contains(textureSender)) - { - m_sharedSendersQueue.Enqueue(textureSender); - } - } - } - else - { - TextureSender requestHandler = - new TextureSender(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber); - m_textureSenders.Add(e.RequestedAssetID, requestHandler); - m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback); - } - } - } - else - { - lock (m_textureSenders) - { - if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) - { - textureSender.Cancel = true; - } - } - } - } - - public void TextureCallback(LLUUID textureID, AssetBase asset) - { - lock (m_textureSenders) - { - TextureSender textureSender; - - if (m_textureSenders.TryGetValue(textureID, out textureSender)) - { - if (!textureSender.ImageLoaded) - { - textureSender.TextureReceived(asset); - textureSender.Sending = true; - textureSender.counter = 0; - - if (!m_sharedSendersQueue.Contains(textureSender)) - { - m_sharedSendersQueue.Enqueue(textureSender); - } - } - } - else - { - throw new Exception("Got a texture with no sender object to handle it, this shouldn't happen"); - } - } - } - } - - public class TextureSender - { - public int counter = 0; - private AssetBase m_asset; - public long DataPointer = 0; - public int NumPackets = 0; - public int PacketCounter = 0; - public bool Cancel = false; - public bool ImageLoaded = false; - - public bool Sending = false; - - public IClientAPI RequestUser; - public LLUUID RequestedAssetID; - public int RequestedDiscardLevel = -1; - public uint StartPacketNumber = 0; - - // private int m_sentDiscardLevel = -1; - - public TextureSender(IClientAPI client, LLUUID textureID, int discardLevel, uint packetNumber) - { - RequestUser = client; - RequestedAssetID = textureID; - RequestedDiscardLevel = discardLevel; - StartPacketNumber = packetNumber; - } - - public void TextureReceived(AssetBase asset) - { - m_asset = asset; - NumPackets = CalculateNumPackets(asset.Data.Length); - PacketCounter = (int) StartPacketNumber; - ImageLoaded = true; - } - - public void UpdateRequest(int discardLevel, uint packetNumber) - { - RequestedDiscardLevel = discardLevel; - StartPacketNumber = packetNumber; - PacketCounter = (int) StartPacketNumber; - } - - public bool SendTexturePacket() - { - SendPacket(); - counter++; - if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) || - ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets/(RequestedDiscardLevel + 1))))) - { - return true; - } - return false; - } - - private void SendPacket() - { - if (PacketCounter <= NumPackets) - { - if (PacketCounter == 0) - { - if (NumPackets == 0) - { - ImageDataPacket im = new ImageDataPacket(); - im.Header.Reliable = false; - im.ImageID.Packets = 1; - im.ImageID.ID = m_asset.FullID; - im.ImageID.Size = (uint) m_asset.Data.Length; - im.ImageData.Data = m_asset.Data; - im.ImageID.Codec = 2; - RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); - PacketCounter++; - } - else - { - ImageDataPacket im = new ImageDataPacket(); - im.Header.Reliable = false; - im.ImageID.Packets = (ushort) (NumPackets); - im.ImageID.ID = m_asset.FullID; - im.ImageID.Size = (uint) m_asset.Data.Length; - im.ImageData.Data = new byte[600]; - Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600); - im.ImageID.Codec = 2; - RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); - PacketCounter++; - } - } - else - { - ImagePacketPacket im = new ImagePacketPacket(); - im.Header.Reliable = false; - im.ImageID.Packet = (ushort) (PacketCounter); - im.ImageID.ID = m_asset.FullID; - int size = m_asset.Data.Length - 600 - (1000*(PacketCounter - 1)); - if (size > 1000) size = 1000; - im.ImageData.Data = new byte[size]; - try - { - Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size); - } - catch (ArgumentOutOfRangeException) - { - MainLog.Instance.Error("TEXTURE", - "Unable to separate texture into multiple packets: Array bounds failure on asset:" + - m_asset.FullID.ToString() ); - return; - } - RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); - PacketCounter++; - } - } - } - - 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; - } - } } } \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/TextureSender.cs b/OpenSim/Region/Environment/Modules/TextureSender.cs new file mode 100644 index 0000000000..aba0126cbe --- /dev/null +++ b/OpenSim/Region/Environment/Modules/TextureSender.cs @@ -0,0 +1,136 @@ +using System; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Console; + +namespace OpenSim.Region.Environment.Modules +{ + public class TextureSender + { + public int counter = 0; + private AssetBase m_asset; + public long DataPointer = 0; + public int NumPackets = 0; + public int PacketCounter = 0; + public bool Cancel = false; + public bool ImageLoaded = false; + + public bool Sending = false; + + public IClientAPI RequestUser; + public LLUUID RequestedAssetID; + public int RequestedDiscardLevel = -1; + public uint StartPacketNumber = 0; + + // private int m_sentDiscardLevel = -1; + + public TextureSender(IClientAPI client, LLUUID textureID, int discardLevel, uint packetNumber) + { + RequestUser = client; + RequestedAssetID = textureID; + RequestedDiscardLevel = discardLevel; + StartPacketNumber = packetNumber; + } + + public void TextureReceived(AssetBase asset) + { + m_asset = asset; + NumPackets = CalculateNumPackets(asset.Data.Length); + PacketCounter = (int) StartPacketNumber; + ImageLoaded = true; + } + + public void UpdateRequest(int discardLevel, uint packetNumber) + { + RequestedDiscardLevel = discardLevel; + StartPacketNumber = packetNumber; + PacketCounter = (int) StartPacketNumber; + } + + public bool SendTexturePacket() + { + SendPacket(); + counter++; + if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) || + ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets/(RequestedDiscardLevel + 1))))) + { + return true; + } + return false; + } + + private void SendPacket() + { + if (PacketCounter <= NumPackets) + { + if (PacketCounter == 0) + { + if (NumPackets == 0) + { + ImageDataPacket im = new ImageDataPacket(); + im.Header.Reliable = false; + im.ImageID.Packets = 1; + im.ImageID.ID = m_asset.FullID; + im.ImageID.Size = (uint) m_asset.Data.Length; + im.ImageData.Data = m_asset.Data; + im.ImageID.Codec = 2; + RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); + PacketCounter++; + } + else + { + ImageDataPacket im = new ImageDataPacket(); + im.Header.Reliable = false; + im.ImageID.Packets = (ushort) (NumPackets); + im.ImageID.ID = m_asset.FullID; + im.ImageID.Size = (uint) m_asset.Data.Length; + im.ImageData.Data = new byte[600]; + Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600); + im.ImageID.Codec = 2; + RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); + PacketCounter++; + } + } + else + { + ImagePacketPacket im = new ImagePacketPacket(); + im.Header.Reliable = false; + im.ImageID.Packet = (ushort) (PacketCounter); + im.ImageID.ID = m_asset.FullID; + int size = m_asset.Data.Length - 600 - (1000*(PacketCounter - 1)); + if (size > 1000) size = 1000; + im.ImageData.Data = new byte[size]; + try + { + Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size); + } + catch (ArgumentOutOfRangeException) + { + MainLog.Instance.Error("TEXTURE", + "Unable to separate texture into multiple packets: Array bounds failure on asset:" + + m_asset.FullID.ToString() ); + return; + } + RequestUser.OutPacket(im, ThrottleOutPacketType.Texture); + PacketCounter++; + } + } + } + + 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; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs b/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs new file mode 100644 index 0000000000..6ee43e218f --- /dev/null +++ b/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules +{ + public class UserTextureDownloadService + { + private readonly Dictionary m_textureSenders = new Dictionary(); + private readonly BlockingQueue m_sharedSendersQueue; + private readonly Scene m_scene; + + public UserTextureDownloadService(Scene scene, BlockingQueue sharedQueue) + { + m_scene = scene; + m_sharedSendersQueue = sharedQueue; + } + + public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e) + { + TextureSender textureSender; + + //TODO: should be working out the data size/ number of packets to be sent for each discard level + if ((e.DiscardLevel >= 0) || (e.Priority != 0)) + { + lock (m_textureSenders) + { + if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) + { + textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber); + + if ((textureSender.ImageLoaded) && + (textureSender.Sending == false)) + { + EnqueueTextureSender(textureSender); + } + } + else + { + TextureSender requestHandler = + new TextureSender(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber); + m_textureSenders.Add(e.RequestedAssetID, requestHandler); + m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback); + } + } + } + else + { + lock (m_textureSenders) + { + if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) + { + textureSender.Cancel = true; + } + } + } + } + + public void TextureCallback(LLUUID textureID, AssetBase asset) + { + lock (m_textureSenders) + { + TextureSender textureSender; + + if (m_textureSenders.TryGetValue(textureID, out textureSender)) + { + if (!textureSender.ImageLoaded) + { + textureSender.TextureReceived(asset); + + EnqueueTextureSender(textureSender); + } + } + else + { + throw new Exception("Got a texture with no sender object to handle it, this shouldn't happen"); + } + } + } + + private void EnqueueTextureSender(TextureSender textureSender) + { + MainLog.Instance.Debug( "TEXTUREDOWNLOAD", "Start: ["+textureSender.RequestedAssetID+"] to ["+textureSender.RequestUser.Name+"]"); + + textureSender.Cancel = false; + textureSender.Sending = true; + textureSender.counter = 0; + + if (!m_sharedSendersQueue.Contains(textureSender)) + { + m_sharedSendersQueue.Enqueue(textureSender); + } + } + } +} \ No newline at end of file