parent
b95efbb689
commit
1d098aa84c
|
@ -132,6 +132,8 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
if (sender.Cancel)
|
if (sender.Cancel)
|
||||||
{
|
{
|
||||||
TextureSent(sender);
|
TextureSent(sender);
|
||||||
|
|
||||||
|
sender.Cancel = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -152,219 +154,5 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
sender.Sending = false;
|
sender.Sending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UserTextureDownloadService
|
|
||||||
{
|
|
||||||
private readonly Dictionary<LLUUID, TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender>();
|
|
||||||
private readonly BlockingQueue<TextureSender> m_sharedSendersQueue;
|
|
||||||
private readonly Scene m_scene;
|
|
||||||
|
|
||||||
public UserTextureDownloadService(Scene scene, BlockingQueue<TextureSender> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<LLUUID, TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender>();
|
||||||
|
private readonly BlockingQueue<TextureSender> m_sharedSendersQueue;
|
||||||
|
private readonly Scene m_scene;
|
||||||
|
|
||||||
|
public UserTextureDownloadService(Scene scene, BlockingQueue<TextureSender> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue