aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/TextureDownloadModule.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/TextureDownloadModule.cs216
1 files changed, 2 insertions, 214 deletions
diff --git a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs b/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs
index 6d5d5e8..4e96572 100644
--- a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs
+++ b/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs
@@ -132,6 +132,8 @@ namespace OpenSim.Region.Environment.Modules
132 if (sender.Cancel) 132 if (sender.Cancel)
133 { 133 {
134 TextureSent(sender); 134 TextureSent(sender);
135
136 sender.Cancel = false;
135 } 137 }
136 else 138 else
137 { 139 {
@@ -152,219 +154,5 @@ namespace OpenSim.Region.Environment.Modules
152 { 154 {
153 sender.Sending = false; 155 sender.Sending = false;
154 } 156 }
155
156 public class UserTextureDownloadService
157 {
158 private readonly Dictionary<LLUUID, TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender>();
159 private readonly BlockingQueue<TextureSender> m_sharedSendersQueue;
160 private readonly Scene m_scene;
161
162 public UserTextureDownloadService(Scene scene, BlockingQueue<TextureSender> sharedQueue)
163 {
164 m_scene = scene;
165 m_sharedSendersQueue = sharedQueue;
166 }
167
168 public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e)
169 {
170 TextureSender textureSender;
171
172 //TODO: should be working out the data size/ number of packets to be sent for each discard level
173 if ((e.DiscardLevel >= 0) || (e.Priority != 0))
174 {
175 lock (m_textureSenders)
176 {
177 if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
178 {
179 textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber);
180 textureSender.counter = 0;
181
182 if ((textureSender.ImageLoaded) &&
183 (textureSender.Sending == false))
184 {
185 textureSender.Sending = true;
186
187 if (!m_sharedSendersQueue.Contains(textureSender))
188 {
189 m_sharedSendersQueue.Enqueue(textureSender);
190 }
191 }
192 }
193 else
194 {
195 TextureSender requestHandler =
196 new TextureSender(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber);
197 m_textureSenders.Add(e.RequestedAssetID, requestHandler);
198 m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback);
199 }
200 }
201 }
202 else
203 {
204 lock (m_textureSenders)
205 {
206 if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender))
207 {
208 textureSender.Cancel = true;
209 }
210 }
211 }
212 }
213
214 public void TextureCallback(LLUUID textureID, AssetBase asset)
215 {
216 lock (m_textureSenders)
217 {
218 TextureSender textureSender;
219
220 if (m_textureSenders.TryGetValue(textureID, out textureSender))
221 {
222 if (!textureSender.ImageLoaded)
223 {
224 textureSender.TextureReceived(asset);
225 textureSender.Sending = true;
226 textureSender.counter = 0;
227
228 if (!m_sharedSendersQueue.Contains(textureSender))
229 {
230 m_sharedSendersQueue.Enqueue(textureSender);
231 }
232 }
233 }
234 else
235 {
236 throw new Exception("Got a texture with no sender object to handle it, this shouldn't happen");
237 }
238 }
239 }
240 }
241
242 public class TextureSender
243 {
244 public int counter = 0;
245 private AssetBase m_asset;
246 public long DataPointer = 0;
247 public int NumPackets = 0;
248 public int PacketCounter = 0;
249 public bool Cancel = false;
250 public bool ImageLoaded = false;
251
252 public bool Sending = false;
253
254 public IClientAPI RequestUser;
255 public LLUUID RequestedAssetID;
256 public int RequestedDiscardLevel = -1;
257 public uint StartPacketNumber = 0;
258
259 // private int m_sentDiscardLevel = -1;
260
261 public TextureSender(IClientAPI client, LLUUID textureID, int discardLevel, uint packetNumber)
262 {
263 RequestUser = client;
264 RequestedAssetID = textureID;
265 RequestedDiscardLevel = discardLevel;
266 StartPacketNumber = packetNumber;
267 }
268
269 public void TextureReceived(AssetBase asset)
270 {
271 m_asset = asset;
272 NumPackets = CalculateNumPackets(asset.Data.Length);
273 PacketCounter = (int) StartPacketNumber;
274 ImageLoaded = true;
275 }
276
277 public void UpdateRequest(int discardLevel, uint packetNumber)
278 {
279 RequestedDiscardLevel = discardLevel;
280 StartPacketNumber = packetNumber;
281 PacketCounter = (int) StartPacketNumber;
282 }
283
284 public bool SendTexturePacket()
285 {
286 SendPacket();
287 counter++;
288 if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) ||
289 ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets/(RequestedDiscardLevel + 1)))))
290 {
291 return true;
292 }
293 return false;
294 }
295
296 private void SendPacket()
297 {
298 if (PacketCounter <= NumPackets)
299 {
300 if (PacketCounter == 0)
301 {
302 if (NumPackets == 0)
303 {
304 ImageDataPacket im = new ImageDataPacket();
305 im.Header.Reliable = false;
306 im.ImageID.Packets = 1;
307 im.ImageID.ID = m_asset.FullID;
308 im.ImageID.Size = (uint) m_asset.Data.Length;
309 im.ImageData.Data = m_asset.Data;
310 im.ImageID.Codec = 2;
311 RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
312 PacketCounter++;
313 }
314 else
315 {
316 ImageDataPacket im = new ImageDataPacket();
317 im.Header.Reliable = false;
318 im.ImageID.Packets = (ushort) (NumPackets);
319 im.ImageID.ID = m_asset.FullID;
320 im.ImageID.Size = (uint) m_asset.Data.Length;
321 im.ImageData.Data = new byte[600];
322 Array.Copy(m_asset.Data, 0, im.ImageData.Data, 0, 600);
323 im.ImageID.Codec = 2;
324 RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
325 PacketCounter++;
326 }
327 }
328 else
329 {
330 ImagePacketPacket im = new ImagePacketPacket();
331 im.Header.Reliable = false;
332 im.ImageID.Packet = (ushort) (PacketCounter);
333 im.ImageID.ID = m_asset.FullID;
334 int size = m_asset.Data.Length - 600 - (1000*(PacketCounter - 1));
335 if (size > 1000) size = 1000;
336 im.ImageData.Data = new byte[size];
337 try
338 {
339 Array.Copy(m_asset.Data, 600 + (1000*(PacketCounter - 1)), im.ImageData.Data, 0, size);
340 }
341 catch (ArgumentOutOfRangeException)
342 {
343 MainLog.Instance.Error("TEXTURE",
344 "Unable to separate texture into multiple packets: Array bounds failure on asset:" +
345 m_asset.FullID.ToString() );
346 return;
347 }
348 RequestUser.OutPacket(im, ThrottleOutPacketType.Texture);
349 PacketCounter++;
350 }
351 }
352 }
353
354 private int CalculateNumPackets(int length)
355 {
356 int numPackets = 0;
357
358 if (length > 600)
359 {
360 //over 600 bytes so split up file
361 int restData = (length - 600);
362 int restPackets = ((restData + 999)/1000);
363 numPackets = restPackets;
364 }
365
366 return numPackets;
367 }
368 }
369 } 157 }
370} \ No newline at end of file 158} \ No newline at end of file