diff options
Diffstat (limited to 'OpenSim/Region/Environment/Modules/TextureDownloadModule.cs')
-rw-r--r-- | OpenSim/Region/Environment/Modules/TextureDownloadModule.cs | 197 |
1 files changed, 192 insertions, 5 deletions
diff --git a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs b/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs index d3297c8..56e20d1 100644 --- a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs +++ b/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs | |||
@@ -25,9 +25,14 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * | 26 | * |
27 | */ | 27 | */ |
28 | 28 | using System; | |
29 | using System.Collections.Generic; | ||
30 | using System.Threading; | ||
29 | using libsecondlife; | 31 | using libsecondlife; |
32 | using libsecondlife.Packets; | ||
30 | using OpenSim.Framework.Interfaces; | 33 | using OpenSim.Framework.Interfaces; |
34 | using OpenSim.Framework.Types; | ||
35 | using OpenSim.Framework.Utilities; | ||
31 | using OpenSim.Region.Environment.Interfaces; | 36 | using OpenSim.Region.Environment.Interfaces; |
32 | using OpenSim.Region.Environment.Scenes; | 37 | using OpenSim.Region.Environment.Scenes; |
33 | using Nini.Config; | 38 | using Nini.Config; |
@@ -37,15 +42,28 @@ namespace OpenSim.Region.Environment.Modules | |||
37 | public class TextureDownloadModule : IRegionModule | 42 | public class TextureDownloadModule : IRegionModule |
38 | { | 43 | { |
39 | private Scene m_scene; | 44 | private Scene m_scene; |
45 | private List<Scene> m_scenes = new List<Scene>(); | ||
46 | private Dictionary<LLUUID, Dictionary<LLUUID, AssetRequest>> ClientRequests = new Dictionary<LLUUID, Dictionary<LLUUID, AssetRequest>>(); | ||
47 | |||
48 | private BlockingQueue<TextureSender> QueueSenders = new BlockingQueue<TextureSender>(); | ||
49 | private Dictionary<LLUUID, List<LLUUID>> InProcess = new Dictionary<LLUUID, List<LLUUID>>(); | ||
50 | // private Thread m_thread; | ||
40 | 51 | ||
41 | public TextureDownloadModule() | 52 | public TextureDownloadModule() |
42 | { | 53 | { |
54 | // m_thread = new Thread(new ThreadStart(ProcessTextureSenders)); | ||
55 | // m_thread.IsBackground = true; | ||
56 | // m_thread.Start(); | ||
43 | } | 57 | } |
44 | 58 | ||
45 | public void Initialise(Scene scene, IConfigSource config) | 59 | public void Initialise(Scene scene, IConfigSource config) |
46 | { | 60 | { |
47 | m_scene = scene; | 61 | if (!m_scenes.Contains(scene)) |
48 | m_scene.EventManager.OnNewClient += NewClient; | 62 | { |
63 | m_scenes.Add(scene); | ||
64 | m_scene = scene; | ||
65 | m_scene.EventManager.OnNewClient += NewClient; | ||
66 | } | ||
49 | } | 67 | } |
50 | 68 | ||
51 | public void PostInitialise() | 69 | public void PostInitialise() |
@@ -63,15 +81,184 @@ namespace OpenSim.Region.Environment.Modules | |||
63 | 81 | ||
64 | public bool IsSharedModule | 82 | public bool IsSharedModule |
65 | { | 83 | { |
66 | get { return false; } | 84 | get { return true; } |
67 | } | 85 | } |
68 | 86 | ||
69 | public void NewClient(IClientAPI client) | 87 | public void NewClient(IClientAPI client) |
70 | { | 88 | { |
89 | /* lock (ClientRequests) | ||
90 | { | ||
91 | if (!ClientRequests.ContainsKey(client.AgentId)) | ||
92 | { | ||
93 | ClientRequests.Add(client.AgentId, new Dictionary<LLUUID, AssetRequest>()); | ||
94 | InProcess.Add(client.AgentId, new List<LLUUID>()); | ||
95 | } | ||
96 | } | ||
97 | client.OnRequestTexture += TextureRequest; | ||
98 | */ | ||
99 | } | ||
100 | |||
101 | public void TextureCallback(LLUUID textureID, AssetBase asset) | ||
102 | { | ||
103 | lock (ClientRequests) | ||
104 | { | ||
105 | foreach (Dictionary<LLUUID, AssetRequest> reqList in ClientRequests.Values) | ||
106 | { | ||
107 | if (reqList.ContainsKey(textureID)) | ||
108 | { | ||
109 | //check the texture isn't already in the process of being sent to the client. | ||
110 | if (!InProcess[reqList[textureID].RequestUser.AgentId].Contains(textureID)) | ||
111 | { | ||
112 | TextureSender sender = new TextureSender(reqList[textureID], asset); | ||
113 | QueueSenders.Enqueue(sender); | ||
114 | InProcess[reqList[textureID].RequestUser.AgentId].Add(textureID); | ||
115 | reqList.Remove(textureID); | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | |||
122 | public void TextureRequest(Object sender, TextureRequestArgs e) | ||
123 | { | ||
124 | IClientAPI client = (IClientAPI)sender; | ||
125 | if (!ClientRequests[client.AgentId].ContainsKey(e.RequestedAssetID)) | ||
126 | { | ||
127 | lock (ClientRequests) | ||
128 | { | ||
129 | AssetRequest request = new AssetRequest(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber); | ||
130 | ClientRequests[client.AgentId].Add(e.RequestedAssetID, request); | ||
131 | } | ||
132 | m_scene.commsManager.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | public void ProcessTextureSenders() | ||
137 | { | ||
138 | while (true) | ||
139 | { | ||
140 | TextureSender sender = this.QueueSenders.Dequeue(); | ||
141 | bool finished = sender.SendTexture(); | ||
142 | if (finished) | ||
143 | { | ||
144 | this.TextureSent(sender); | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | this.QueueSenders.Enqueue(sender); | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | |||
153 | private void TextureSent(TextureSender sender) | ||
154 | { | ||
155 | if (InProcess[sender.request.RequestUser.AgentId].Contains(sender.request.RequestAssetID)) | ||
156 | { | ||
157 | InProcess[sender.request.RequestUser.AgentId].Remove(sender.request.RequestAssetID); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | public class TextureSender | ||
162 | { | ||
163 | public AssetRequest request; | ||
164 | private int counter = 0; | ||
165 | private AssetBase m_asset; | ||
166 | public long DataPointer = 0; | ||
167 | public int NumPackets = 0; | ||
168 | public int PacketCounter = 0; | ||
169 | |||
170 | public TextureSender(AssetRequest req, AssetBase asset) | ||
171 | { | ||
172 | request = req; | ||
173 | m_asset = asset; | ||
174 | |||
175 | if (asset.Data.LongLength > 600) | ||
176 | { | ||
177 | NumPackets = 2 + (int)(asset.Data.Length - 601) / 1000; | ||
178 | } | ||
179 | else | ||
180 | { | ||
181 | NumPackets = 1; | ||
182 | } | ||
183 | |||
184 | PacketCounter = (int) req.PacketNumber; | ||
185 | } | ||
186 | |||
187 | public bool SendTexture() | ||
188 | { | ||
189 | SendPacket(); | ||
190 | counter++; | ||
191 | if ((PacketCounter >= NumPackets) | counter > 100 | (NumPackets == 1) | (request.DiscardLevel == -1)) | ||
192 | { | ||
193 | return true; | ||
194 | } | ||
195 | return false; | ||
196 | } | ||
197 | |||
198 | public void SendPacket() | ||
199 | { | ||
200 | AssetRequest req = request; | ||
201 | if (PacketCounter == 0) | ||
202 | { | ||
203 | if (NumPackets == 1) | ||
204 | { | ||
205 | ImageDataPacket im = new ImageDataPacket(); | ||
206 | im.Header.Reliable = false; | ||
207 | im.ImageID.Packets = 1; | ||
208 | im.ImageID.ID = m_asset.FullID; | ||
209 | im.ImageID.Size = (uint)m_asset.Data.Length; | ||
210 | im.ImageData.Data = m_asset.Data; | ||
211 | im.ImageID.Codec = 2; | ||
212 | req.RequestUser.OutPacket(im); | ||
213 | PacketCounter++; | ||
214 | } | ||
215 | else | ||
216 | { | ||
217 | ImageDataPacket im = new ImageDataPacket(); | ||
218 | im.Header.Reliable = false; | ||
219 | im.ImageID.Packets = (ushort)(NumPackets); | ||
220 | im.ImageID.ID = m_asset.FullID; | ||
221 | im.ImageID.Size = (uint)m_asset.Data.Length; | ||
222 | im.ImageData.Data = new byte[600]; | ||
223 | Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600); | ||
224 | im.ImageID.Codec = 2; | ||
225 | req.RequestUser.OutPacket(im); | ||
226 | PacketCounter++; | ||
227 | } | ||
228 | } | ||
229 | else | ||
230 | { | ||
231 | ImagePacketPacket im = new ImagePacketPacket(); | ||
232 | im.Header.Reliable = false; | ||
233 | im.ImageID.Packet = (ushort)(PacketCounter); | ||
234 | im.ImageID.ID = m_asset.FullID; | ||
235 | int size = m_asset.Data.Length - 600 - (1000 * (PacketCounter - 1)); | ||
236 | if (size > 1000) size = 1000; | ||
237 | im.ImageData.Data = new byte[size]; | ||
238 | Array.Copy(m_asset.Data, 600 + (1000 * (PacketCounter - 1)), im.ImageData.Data, 0, size); | ||
239 | req.RequestUser.OutPacket(im); | ||
240 | PacketCounter++; | ||
241 | } | ||
242 | |||
243 | } | ||
244 | |||
71 | } | 245 | } |
72 | 246 | ||
73 | public void TextureAssetCallback(LLUUID texture, byte[] data) | 247 | public class AssetRequest |
74 | { | 248 | { |
249 | public IClientAPI RequestUser; | ||
250 | public LLUUID RequestAssetID; | ||
251 | public int DiscardLevel = -1; | ||
252 | public uint PacketNumber = 0; | ||
253 | |||
254 | public AssetRequest(IClientAPI client, LLUUID textureID, int discardLevel, uint packetNumber) | ||
255 | { | ||
256 | RequestUser = client; | ||
257 | RequestAssetID = textureID; | ||
258 | DiscardLevel = discardLevel; | ||
259 | PacketNumber = packetNumber; | ||
260 | } | ||
75 | } | 261 | } |
262 | |||
76 | } | 263 | } |
77 | } | 264 | } |