diff options
Diffstat (limited to 'OpenSim/Region/Environment/Modules/TextureDownloadModule.cs')
-rw-r--r-- | OpenSim/Region/Environment/Modules/TextureDownloadModule.cs | 216 |
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 |