123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- /*
- * 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.Generic;
- using libsecondlife;
- using libsecondlife.Packets;
- using Nini.Config;
- using OpenSim.Framework;
- using OpenSim.Region.Environment.Interfaces;
- using OpenSim.Region.Environment.Scenes;
- namespace OpenSim.Region.Environment.Modules
- {
- public class TextureDownloadModule : IRegionModule
- {
- private Scene m_scene;
- private List<Scene> m_scenes = new List<Scene>();
- private Dictionary<LLUUID, Dictionary<LLUUID, AssetRequest>> ClientRequests =
- new Dictionary<LLUUID, Dictionary<LLUUID, AssetRequest>>();
- private BlockingQueue<TextureSender> QueueSenders = new BlockingQueue<TextureSender>();
- private Dictionary<LLUUID, List<LLUUID>> InProcess = new Dictionary<LLUUID, List<LLUUID>>();
- // private Thread m_thread;
- public TextureDownloadModule()
- {
- // m_thread = new Thread(new ThreadStart(ProcessTextureSenders));
- // m_thread.IsBackground = true;
- // m_thread.Start();
- }
- public void Initialise(Scene scene, IConfigSource config)
- {
- if (!m_scenes.Contains(scene))
- {
- m_scenes.Add(scene);
- m_scene = scene;
- m_scene.EventManager.OnNewClient += NewClient;
- }
- }
- public void PostInitialise()
- {
- }
- public void Close()
- {
- }
- public string Name
- {
- get { return "TextureDownloadModule"; }
- }
- public bool IsSharedModule
- {
- get { return true; }
- }
- public void NewClient(IClientAPI client)
- {
- /* lock (ClientRequests)
- {
- if (!ClientRequests.ContainsKey(client.AgentId))
- {
- ClientRequests.Add(client.AgentId, new Dictionary<LLUUID, AssetRequest>());
- InProcess.Add(client.AgentId, new List<LLUUID>());
- }
- }
- client.OnRequestTexture += TextureRequest;
- */
- }
- public void TextureCallback(LLUUID textureID, AssetBase asset)
- {
- lock (ClientRequests)
- {
- foreach (Dictionary<LLUUID, AssetRequest> reqList in ClientRequests.Values)
- {
- if (reqList.ContainsKey(textureID))
- {
- //check the texture isn't already in the process of being sent to the client.
- if (!InProcess[reqList[textureID].RequestUser.AgentId].Contains(textureID))
- {
- TextureSender sender = new TextureSender(reqList[textureID], asset);
- QueueSenders.Enqueue(sender);
- InProcess[reqList[textureID].RequestUser.AgentId].Add(textureID);
- reqList.Remove(textureID);
- }
- }
- }
- }
- }
- public void TextureRequest(Object sender, TextureRequestArgs e)
- {
- IClientAPI client = (IClientAPI) sender;
- if (!ClientRequests[client.AgentId].ContainsKey(e.RequestedAssetID))
- {
- lock (ClientRequests)
- {
- AssetRequest request = new AssetRequest(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber);
- ClientRequests[client.AgentId].Add(e.RequestedAssetID, request);
- }
- m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback);
- }
- }
- public void ProcessTextureSenders()
- {
- while (true)
- {
- TextureSender sender = QueueSenders.Dequeue();
- bool finished = sender.SendTexture();
- if (finished)
- {
- TextureSent(sender);
- }
- else
- {
- QueueSenders.Enqueue(sender);
- }
- }
- }
- private void TextureSent(TextureSender sender)
- {
- if (InProcess[sender.request.RequestUser.AgentId].Contains(sender.request.RequestAssetID))
- {
- InProcess[sender.request.RequestUser.AgentId].Remove(sender.request.RequestAssetID);
- }
- }
- public class TextureSender
- {
- public AssetRequest request;
- private int counter = 0;
- private AssetBase m_asset;
- public long DataPointer = 0;
- public int NumPackets = 0;
- public int PacketCounter = 0;
- public TextureSender(AssetRequest req, AssetBase asset)
- {
- request = req;
- m_asset = asset;
- if (asset.Data.LongLength > 600)
- {
- NumPackets = 2 + (int) (asset.Data.Length - 601)/1000;
- }
- else
- {
- NumPackets = 1;
- }
- PacketCounter = (int) req.PacketNumber;
- }
- public bool SendTexture()
- {
- SendPacket();
- counter++;
- if ((PacketCounter >= NumPackets) || counter > 100 || (NumPackets == 1) || (request.DiscardLevel == -1))
- {
- return true;
- }
- return false;
- }
- public void SendPacket()
- {
- AssetRequest req = request;
- if (PacketCounter == 0)
- {
- if (NumPackets == 1)
- {
- 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;
- req.RequestUser.OutPacket(im);
- 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;
- req.RequestUser.OutPacket(im);
- 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];
- Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size);
- req.RequestUser.OutPacket(im);
- PacketCounter++;
- }
- }
- }
- public class AssetRequest
- {
- public IClientAPI RequestUser;
- public LLUUID RequestAssetID;
- public int DiscardLevel = -1;
- public uint PacketNumber = 0;
- public AssetRequest(IClientAPI client, LLUUID textureID, int discardLevel, uint packetNumber)
- {
- RequestUser = client;
- RequestAssetID = textureID;
- DiscardLevel = discardLevel;
- PacketNumber = packetNumber;
- }
- }
- }
- }
|