示例#1
0
        /// <summary>
        /// Handles the remaining Image data that did not fit in the initial ImageData packet
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="simulator"></param>
        public void ImagePacketCallbackHandler(Packet packet, Simulator simulator)
        {
#if DEBUG_PACKETS
            slClient.DebugLog(packet);
#endif

            ImagePacketPacket reply = (ImagePacketPacket)packet;

            LLUUID ImageID = reply.ImageID.ID;

            // Lookup the request for this packet
            TransferRequest tr = null;
            lock (htDownloadRequests)
            {
                if (htDownloadRequests.ContainsKey(ImageID))
                {
                    tr = (TransferRequest)htDownloadRequests[ImageID];
                }
                else
                {
                    // Received a packet that doesn't belong to any requests in our queue, strange...
                    return;
                }
            }


            // TODO: Received data should probably be put into a temporary collection that's indected by ImageID.Packet
            // then once we've received all data packets, it should be re-assembled into a complete array and marked
            // completed.

            // FIXME: Sometimes this gets called before ImageDataCallbackHandler, when that
            // happens tr.AssetData will be null.  Implimenting the above TODO should fix this.

            // Wait until we've received the header packet for this image, which creates the AssetData array
            if (!tr.ReceivedHeaderPacket.WaitOne(15000, false))
            {
                tr.Status    = false;
                tr.StatusMsg = "Failed to receive Image Header packet in a timely manor, aborting.";
                slClient.Log(tr.StatusMsg, Helpers.LogLevel.Error);
                tr.Completed.Set();
            }

            // Add this packet's data to the request.
            Buffer.BlockCopy(reply.ImageData.Data, 0, tr.AssetData, tr.BaseDataReceived + (1000 * (reply.ImageID.Packet - 1)), reply.ImageData.Data.Length);
            tr.Received += (uint)reply.ImageData.Data.Length;

            tr.TimeOfLastPacket = Helpers.GetUnixTime(); // last time we recevied a packet for this request

            // If we've gotten all the data, mark it completed.
            if (tr.Received >= tr.Size)
            {
                tr.Status = true;
                tr.Completed.Set();

                // Fire off image downloaded event
                CacheImage(ImageID, tr.AssetData);
                FireImageRetrieved(ImageID, tr.AssetData, false);
            }
        }
示例#2
0
        public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData)
        {
            ImagePacketPacket im = new ImagePacketPacket();

            im.Header.Reliable = false;
            im.ImageID.Packet  = partNumber;
            im.ImageID.ID      = imageUuid;
            im.ImageData.Data  = imageData;
            sentpktpkt.Add(im);
        }
示例#3
0
        private void SendImageNextPart(ushort packetNumber, byte[] imageData)
        {
            ImagePacketPacket packet = new ImagePacketPacket();

            packet.ImageID.ID     = TextureID;
            packet.ImageID.Packet = packetNumber;

            packet.ImageData.Data = imageData;

            m_udp.SendPacket(m_agent, packet, ThrottleCategory.Texture, false);
        }
示例#4
0
        /// <summary>
        /// Handles the remaining Image data that did not fit in the initial ImageData packet
        /// </summary>
        private void ImagePacketHandler(Packet packet, Simulator simulator)
        {
            ImagePacketPacket image    = (ImagePacketPacket)packet;
            ImageDownload     transfer = null;

            lock (Transfers)
            {
                if (Transfers.ContainsKey(image.ImageID.ID))
                {
                    transfer = (ImageDownload)Transfers[image.ImageID.ID];

                    if (transfer.Size == 0)
                    {
                        // We haven't received the header yet, block until it's received or times out
                        transfer.HeaderReceivedEvent.WaitOne(1000 * 20, false);

                        if (transfer.Size == 0)
                        {
                            Client.Log("Timed out while waiting for the image header to download for " +
                                       transfer.ID.ToString(), Helpers.LogLevel.Warning);

                            transfer.Success = false;
                            Transfers.Remove(transfer.ID);
                            goto Callback;
                        }
                    }

                    // The header is downloaded, we can insert this data in to the proper position
                    Array.Copy(image.ImageData.Data, 0, transfer.AssetData, transfer.InitialDataSize +
                               (1000 * (image.ImageID.Packet - 1)), image.ImageData.Data.Length);
                    transfer.Transferred += image.ImageData.Data.Length;

                    //Client.DebugLog("Received " + image.ImageData.Data.Length + "/" + transfer.Transferred +
                    //    "/" + transfer.Size + " bytes for image " + image.ImageID.ID.ToString());

                    // Check if we downloaded the full image
                    if (transfer.Transferred >= transfer.Size)
                    {
                        transfer.Success = true;
                        Transfers.Remove(transfer.ID);
                    }
                }
            }

Callback:

            if (transfer != null && OnImageReceived != null && (transfer.Transferred >= transfer.Size || transfer.Size == 0))
            {
                try { OnImageReceived(transfer, new AssetTexture(transfer.AssetData)); }
                catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
            }
        }
示例#5
0
        /// <summary>
        /// Handles the remaining Image data that did not fit in the initial ImageData packet
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="simulator"></param>
        public void ImagePacketCallbackHandler(Packet packet, Simulator simulator)
        {
            #if DEBUG_PACKETS
            Console.WriteLine(packet);
            #endif

            ImagePacketPacket reply = (ImagePacketPacket)packet;

            LLUUID ImageID = reply.ImageID.ID;

            // Lookup the request for this packet
            TransferRequest tr;
            lock (htDownloadRequests)
            {
                tr = (TransferRequest)htDownloadRequests[ImageID];
            }
            if (tr == null)
            {
                // Received a packet that doesn't belong to any requests in our queue, strange...
                return;
            }


            // TODO: Received data should probably be put into a temporary collection that's indected by ImageID.Packet
            // then once we've received all data packets, it should be re-assembled into a complete array and marked
            // completed.

            // FIXME: Sometimes this gets called before ImageDataCallbackHandler, when that
            // happens tr.AssetData will be null.  Implimenting the above TODO should fix this.

            // Wait until we've received the header packet for this image, which creates the AssetData array
            tr.ReceivedHeaderPacket.WaitOne();

            // Add this packet's data to the request.
            Array.Copy(reply.ImageData.Data, 0, tr.AssetData, tr.BaseDataReceived + (1000 * (reply.ImageID.Packet - 1)), reply.ImageData.Data.Length);
            tr.Received += (uint)reply.ImageData.Data.Length;

            // If we've gotten all the data, mark it completed.
            if (tr.Received >= tr.Size)
            {
                tr.Status = true;
                tr.Completed.Set();

                // Fire off image downloaded event
                CacheImage(ImageID, tr.AssetData);
                FireImageRetrieved(ImageID, tr.AssetData, false);
            }
        }
        /// <summary>
        /// Handles the remaining Image data that did not fit in the initial ImageData packet
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The EventArgs object containing the packet data</param>
        protected void ImagePacketHandler(object sender, PacketReceivedEventArgs e)
        {
            ImagePacketPacket image = (ImagePacketPacket)e.Packet;
            TaskInfo          task;

            if (TryGetTransferValue(image.ImageID.ID, out task))
            {
                if (task.Transfer.Size == 0)
                {
                    // We haven't received the header yet, block until it's received or times out
                    task.Transfer.HeaderReceivedEvent.WaitOne(1000 * 5, false);

                    if (task.Transfer.Size == 0)
                    {
                        Logger.Log("Timed out while waiting for the image header to download for " +
                                   task.Transfer.ID, Helpers.LogLevel.Warning, _Client);

                        RemoveTransfer(task.Transfer.ID);
                        resetEvents[task.RequestSlot].Set(); // free up request slot

                        foreach (TextureDownloadCallback callback in task.Callbacks)
                        {
                            callback(TextureRequestState.Timeout, new AssetTexture(task.RequestID, task.Transfer.AssetData));
                        }

                        return;
                    }
                }

                // The header is downloaded, we can insert this data in to the proper position
                // Only insert if we haven't seen this packet before
                lock (task.Transfer)
                {
                    if (!task.Transfer.PacketsSeen.ContainsKey(image.ImageID.Packet))
                    {
                        task.Transfer.PacketsSeen[image.ImageID.Packet] = image.ImageID.Packet;
                        Buffer.BlockCopy(image.ImageData.Data, 0, task.Transfer.AssetData,
                                         task.Transfer.InitialDataSize + (1000 * (image.ImageID.Packet - 1)),
                                         image.ImageData.Data.Length);
                        task.Transfer.Transferred += image.ImageData.Data.Length;
                    }
                }

                task.Transfer.TimeSinceLastPacket = 0;

                if (task.Transfer.Transferred >= task.Transfer.Size)
                {
#if DEBUG_TIMING
                    DateTime stopTime        = DateTime.UtcNow;
                    TimeSpan requestDuration = stopTime - task.StartTime;

                    TimeSpan networkDuration = stopTime - task.NetworkTime;

                    TotalTime   += requestDuration;
                    NetworkTime += networkDuration;
                    TotalBytes  += task.Transfer.Size;

                    Logger.Log(
                        String.Format(
                            "Transfer Complete {0} [{1}] Total Request Time: {2}, Download Time {3}, Network {4}Kb/sec, Image Size {5} bytes",
                            task.RequestID, task.RequestSlot, requestDuration, networkDuration,
                            Math.Round(task.Transfer.Size / networkDuration.TotalSeconds / 60, 2), task.Transfer.Size),
                        Helpers.LogLevel.Debug);
#endif

                    task.Transfer.Success = true;
                    RemoveTransfer(task.Transfer.ID);
                    resetEvents[task.RequestSlot].Set(); // free up request slot
                    _Client.Assets.Cache.SaveAssetToCache(task.RequestID, task.Transfer.AssetData);
                    foreach (TextureDownloadCallback callback in task.Callbacks)
                    {
                        callback(TextureRequestState.Finished, new AssetTexture(task.RequestID, task.Transfer.AssetData));
                    }

                    _Client.Assets.FireImageProgressEvent(task.RequestID, task.Transfer.Transferred, task.Transfer.Size);
                }
                else
                {
                    if (task.ReportProgress)
                    {
                        foreach (TextureDownloadCallback callback in task.Callbacks)
                        {
                            callback(TextureRequestState.Progress,
                                     new AssetTexture(task.RequestID, task.Transfer.AssetData));
                        }
                    }
                    _Client.Assets.FireImageProgressEvent(task.RequestID, task.Transfer.Transferred,
                                                          task.Transfer.Size);
                }
            }
        }
        void SendTexture(Agent agent, AssetTexture texture, int discardLevel, int packet, float priority)
        {
            ImageDownload download = new ImageDownload(texture, agent, discardLevel, priority, packet);

            Logger.DebugLog(String.Format(
                "[Periscope] Starting new texture transfer for {0}, DiscardLevel: {1}, Priority: {2}, Start: {3}, End: {4}, Total: {5}",
                texture.AssetID, discardLevel, priority, download.CurrentPacket, download.StopPacket, download.TexturePacketCount()));

            // Send initial data
            ImageDataPacket data = new ImageDataPacket();
            data.ImageID.Codec = (byte)ImageCodec.J2C;
            data.ImageID.ID = download.Texture.AssetID;
            data.ImageID.Packets = (ushort)download.TexturePacketCount();
            data.ImageID.Size = (uint)download.Texture.AssetData.Length;

            // The first bytes of the image are always sent in the ImageData packet
            data.ImageData = new ImageDataPacket.ImageDataBlock();
            int imageDataSize = (download.Texture.AssetData.Length >= ImageDownload.FIRST_IMAGE_PACKET_SIZE) ?
                ImageDownload.FIRST_IMAGE_PACKET_SIZE : download.Texture.AssetData.Length;
            try
            {
                data.ImageData.Data = new byte[imageDataSize];
                Buffer.BlockCopy(download.Texture.AssetData, 0, data.ImageData.Data, 0, imageDataSize);
            }
            catch (Exception ex)
            {
                Logger.Log(String.Format("{0}: imageDataSize={1}", ex.Message, imageDataSize),
                    Helpers.LogLevel.Error);
            }

            server.UDP.SendPacket(agent.Avatar.ID, data, PacketCategory.Texture);

            // Check if ImagePacket packets need to be sent to complete this transfer
            if (download.CurrentPacket <= download.StopPacket)
            {
                // Insert this download into the dictionary
                lock (currentDownloads)
                    currentDownloads[texture.AssetID] = download;

                // Send all of the remaining packets
                ThreadPool.QueueUserWorkItem(
                    delegate(object obj)
                    {
                        while (download.CurrentPacket <= download.StopPacket)
                        {
                            if (download.Priority == 0.0f && download.DiscardLevel == -1)
                                break;

                            lock (download)
                            {
                                int imagePacketSize = (download.CurrentPacket == download.TexturePacketCount() - 1) ?
                                    download.LastPacketSize() : ImageDownload.IMAGE_PACKET_SIZE;

                                ImagePacketPacket transfer = new ImagePacketPacket();
                                transfer.ImageID.ID = texture.AssetID;
                                transfer.ImageID.Packet = (ushort)download.CurrentPacket;
                                transfer.ImageData.Data = new byte[imagePacketSize];

                                try
                                {
                                    Buffer.BlockCopy(download.Texture.AssetData, download.CurrentBytePosition(),
                                        transfer.ImageData.Data, 0, imagePacketSize);
                                }
                                catch (Exception ex)
                                {
                                    Logger.Log(String.Format(
                                        "{0}: CurrentBytePosition()={1}, AssetData.Length={2} imagePacketSize={3}",
                                        ex.Message, download.CurrentBytePosition(), download.Texture.AssetData.Length,
                                        imagePacketSize), Helpers.LogLevel.Error);
                                }

                                server.UDP.SendPacket(agent.Avatar.ID, transfer, PacketCategory.Texture);

                                ++download.CurrentPacket;
                            }
                        }

                        Logger.DebugLog("Completed image transfer for " + texture.AssetID.ToString());

                        // Transfer is complete, remove the reference
                        lock (currentDownloads)
                            currentDownloads.Remove(texture.AssetID);
                    }
                );
            }
        }
示例#8
0
        void RequestImageHandler(Packet packet, Agent agent)
        {
            RequestImagePacket request = (RequestImagePacket)packet;

            for (int i = 0; i < request.RequestImage.Length; i++)
            {
                RequestImagePacket.RequestImageBlock block = request.RequestImage[i];

                ImageDownload download;
                bool          downloadFound = CurrentDownloads.TryGetValue(block.Image, out download);

                if (downloadFound)
                {
                    lock (download)
                    {
                        if (block.DiscardLevel == -1 && block.DownloadPriority == 0.0f)
                        {
                            Logger.DebugLog(String.Format("Image download {0} is aborting", block.Image));
                        }
                        else
                        {
                            if (block.DiscardLevel < download.DiscardLevel)
                            {
                                Logger.DebugLog(String.Format("Image download {0} is changing from DiscardLevel {1} to {2}",
                                                              block.Image, download.DiscardLevel, block.DiscardLevel));
                            }

                            if (block.DownloadPriority != download.Priority)
                            {
                                Logger.DebugLog(String.Format("Image download {0} is changing from Priority {1} to {2}",
                                                              block.Image, download.Priority, block.DownloadPriority));
                            }

                            if (block.Packet != download.CurrentPacket)
                            {
                                Logger.DebugLog(String.Format("Image download {0} is changing from Packet {1} to {2}",
                                                              block.Image, download.CurrentPacket, block.Packet));
                            }
                        }

                        // Update download
                        download.Update(block.DiscardLevel, block.DownloadPriority, (int)block.Packet);
                    }
                }
                else if (block.DiscardLevel == -1 && block.DownloadPriority == 0.0f)
                {
                    // Aborting a download we are not tracking, ignore
                    Logger.DebugLog(String.Format("Aborting an image download for untracked image " + block.Image.ToString()));
                }
                else
                {
                    bool bake = ((ImageType)block.Type == ImageType.Baked);

                    // New download, check if we have this image
                    Asset asset;
                    if (server.Assets.TryGetAsset(block.Image, out asset) && asset is AssetTexture)
                    {
                        download = new ImageDownload((AssetTexture)asset, block.DiscardLevel, block.DownloadPriority,
                                                     (int)block.Packet);

                        Logger.DebugLog(String.Format(
                                            "Starting new download for {0}, DiscardLevel: {1}, Priority: {2}, Start: {3}, End: {4}, Total: {5}",
                                            block.Image, block.DiscardLevel, block.DownloadPriority, download.CurrentPacket, download.StopPacket,
                                            download.TexturePacketCount()));

                        // Send initial data
                        ImageDataPacket data = new ImageDataPacket();
                        data.ImageID.Codec   = (byte)ImageCodec.J2C;
                        data.ImageID.ID      = download.Texture.AssetID;
                        data.ImageID.Packets = (ushort)download.TexturePacketCount();
                        data.ImageID.Size    = (uint)download.Texture.AssetData.Length;

                        // The first bytes of the image are always sent in the ImageData packet
                        data.ImageData = new ImageDataPacket.ImageDataBlock();
                        int imageDataSize = (download.Texture.AssetData.Length >= ImageDownload.FIRST_IMAGE_PACKET_SIZE) ?
                                            ImageDownload.FIRST_IMAGE_PACKET_SIZE : download.Texture.AssetData.Length;
                        data.ImageData.Data = new byte[imageDataSize];
                        Buffer.BlockCopy(download.Texture.AssetData, 0, data.ImageData.Data, 0, imageDataSize);

                        server.UDP.SendPacket(agent.AgentID, data, PacketCategory.Texture);

                        // Check if ImagePacket packets need to be sent to complete this transfer
                        if (download.CurrentPacket <= download.StopPacket)
                        {
                            // Insert this download into the dictionary
                            lock (CurrentDownloads)
                                CurrentDownloads[block.Image] = download;

                            // Send all of the remaining packets
                            ThreadPool.QueueUserWorkItem(
                                delegate(object obj)
                            {
                                while (download.CurrentPacket <= download.StopPacket)
                                {
                                    if (download.Priority == 0.0f && download.DiscardLevel == -1)
                                    {
                                        break;
                                    }

                                    lock (download)
                                    {
                                        int imagePacketSize = (download.CurrentPacket == download.TexturePacketCount() - 1) ?
                                                              download.LastPacketSize() : ImageDownload.IMAGE_PACKET_SIZE;

                                        ImagePacketPacket transfer = new ImagePacketPacket();
                                        transfer.ImageID.ID        = block.Image;
                                        transfer.ImageID.Packet    = (ushort)download.CurrentPacket;
                                        transfer.ImageData.Data    = new byte[imagePacketSize];
                                        Buffer.BlockCopy(download.Texture.AssetData, download.CurrentBytePosition(),
                                                         transfer.ImageData.Data, 0, imagePacketSize);

                                        server.UDP.SendPacket(agent.AgentID, transfer, PacketCategory.Texture);

                                        ++download.CurrentPacket;
                                    }
                                }

                                Logger.DebugLog("Completed image transfer for " + block.Image.ToString());

                                // Transfer is complete, remove the reference
                                lock (CurrentDownloads)
                                    CurrentDownloads.Remove(block.Image);
                            }
                                );
                        }
                    }
                    else
                    {
                        Logger.Log("Request for a missing texture " + block.Image.ToString(), Helpers.LogLevel.Warning);

                        ImageNotInDatabasePacket notfound = new ImageNotInDatabasePacket();
                        notfound.ImageID.ID = block.Image;
                        server.UDP.SendPacket(agent.AgentID, notfound, PacketCategory.Texture);
                    }
                }
            }
        }
示例#9
0
        /// <summary>
        /// 
        /// </summary>
        private void ProcessTextureQueue()
        {
            if (this.TextureRequests.Count == 0)
            {
                //no requests waiting
                return;
            }
            int num;

            if (this.TextureRequests.Count < 5)
            {
                //lower than 5 so do all of them
                num = this.TextureRequests.Count;
            }
            else
            {
                num = 5;
            }
            AssetRequest req;
            for (int i = 0; i < num; i++)
            {
                req = (AssetRequest)this.TextureRequests[i];
                if (req.PacketCounter != req.NumPackets)
                {
                    // if (req.ImageInfo.FullID == new LLUUID("00000000-0000-0000-5005-000000000005"))
                    if (req.PacketCounter == 0)
                    {
                        //first time for this request so send imagedata packet
                        if (req.NumPackets == 1)
                        {
                            //only one packet so send whole file
                            ImageDataPacket im = new ImageDataPacket();
                            im.ImageID.Packets = 1;
                            im.ImageID.ID = req.ImageInfo.FullID;
                            im.ImageID.Size = (uint)req.ImageInfo.Data.Length;
                            im.ImageData.Data = req.ImageInfo.Data;
                            im.ImageID.Codec = 2;
                            req.RequestUser.OutPacket(im);
                            req.PacketCounter++;
                            //req.ImageInfo.l= time;
                            //System.Console.WriteLine("sent texture: "+req.image_info.FullID);
                        }
                        else
                        {
                            //more than one packet so split file up
                            ImageDataPacket im = new ImageDataPacket();
                            im.ImageID.Packets = (ushort)req.NumPackets;
                            im.ImageID.ID = req.ImageInfo.FullID;
                            im.ImageID.Size = (uint)req.ImageInfo.Data.Length;
                            im.ImageData.Data = new byte[600];
                            Array.Copy(req.ImageInfo.Data, 0, im.ImageData.Data, 0, 600);
                            im.ImageID.Codec = 2;
                            req.RequestUser.OutPacket(im);
                            req.PacketCounter++;
                            //req.ImageInfo.last_used = time;
                            //System.Console.WriteLine("sent first packet of texture:
                        }
                    }
                    else
                    {
                         //send imagepacket
                        //more than one packet so split file up
                        ImagePacketPacket im = new ImagePacketPacket();
                        im.ImageID.Packet = (ushort)req.PacketCounter;
                        im.ImageID.ID = req.ImageInfo.FullID;
                        int size = req.ImageInfo.Data.Length - 600 - 1000 * (req.PacketCounter - 1);
                        if (size > 1000) size = 1000;
                        im.ImageData.Data = new byte[size];
                        Array.Copy(req.ImageInfo.Data, 600 + 1000 * (req.PacketCounter - 1), im.ImageData.Data, 0, size);
                        req.RequestUser.OutPacket(im);
                        req.PacketCounter++;
                        //req.ImageInfo.last_used = time;
                        //System.Console.WriteLine("sent a packet of texture: "+req.image_info.FullID);
                    }
                }
            }

            //remove requests that have been completed
            int count = 0;
            for (int i = 0; i < num; i++)
            {
                if (this.TextureRequests.Count > count)
                {
                    req = (AssetRequest)this.TextureRequests[count];
                    if (req.PacketCounter == req.NumPackets)
                    {
                        this.TextureRequests.Remove(req);
                    }
                    else
                    {
                        count++;
                    }
                }
            }
        }
示例#10
0
        public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData)
        {
            ImagePacketPacket im = new ImagePacketPacket();
            im.Header.Reliable = true;
            im.ImageID.Packet = partNumber;
            im.ImageID.ID = imageUuid;
            im.ImageData.Data = imageData;

            //OutPacket(im, ThrottleOutPacketType.Texture);
            proxy.InjectPacket(im, Direction.Incoming);
        }
示例#11
0
        /// <summary>
        ///
        /// </summary>
        private void ProcessTextureQueue()
        {
            if (this.TextureRequests.Count == 0)
            {
                //no requests waiting
                return;
            }
            int num;

            if (this.TextureRequests.Count < 5)
            {
                //lower than 5 so do all of them
                num = this.TextureRequests.Count;
            }
            else
            {
                num = 5;
            }
            AssetRequest req;

            for (int i = 0; i < num; i++)
            {
                req = (AssetRequest)this.TextureRequests[i];
                if (req.PacketCounter != req.NumPackets)
                {
                    // if (req.ImageInfo.FullID == new LLUUID("00000000-0000-0000-5005-000000000005"))
                    if (req.PacketCounter == 0)
                    {
                        //first time for this request so send imagedata packet
                        if (req.NumPackets == 1)
                        {
                            //only one packet so send whole file
                            ImageDataPacket im = new ImageDataPacket();
                            im.ImageID.Packets = 1;
                            im.ImageID.ID      = req.ImageInfo.FullID;
                            im.ImageID.Size    = (uint)req.ImageInfo.Data.Length;
                            im.ImageData.Data  = req.ImageInfo.Data;
                            im.ImageID.Codec   = 2;
                            req.RequestUser.OutPacket(im);
                            req.PacketCounter++;
                            //req.ImageInfo.l= time;
                            //System.Console.WriteLine("sent texture: "+req.image_info.FullID);
                        }
                        else
                        {
                            //more than one packet so split file up
                            ImageDataPacket im = new ImageDataPacket();
                            im.ImageID.Packets = (ushort)req.NumPackets;
                            im.ImageID.ID      = req.ImageInfo.FullID;
                            im.ImageID.Size    = (uint)req.ImageInfo.Data.Length;
                            im.ImageData.Data  = new byte[600];
                            Array.Copy(req.ImageInfo.Data, 0, im.ImageData.Data, 0, 600);
                            im.ImageID.Codec = 2;
                            req.RequestUser.OutPacket(im);
                            req.PacketCounter++;
                            //req.ImageInfo.last_used = time;
                            //System.Console.WriteLine("sent first packet of texture:
                        }
                    }
                    else
                    {
                        //send imagepacket
                        //more than one packet so split file up
                        ImagePacketPacket im = new ImagePacketPacket();
                        im.ImageID.Packet = (ushort)req.PacketCounter;
                        im.ImageID.ID     = req.ImageInfo.FullID;
                        int size = req.ImageInfo.Data.Length - 600 - 1000 * (req.PacketCounter - 1);
                        if (size > 1000)
                        {
                            size = 1000;
                        }
                        im.ImageData.Data = new byte[size];
                        Array.Copy(req.ImageInfo.Data, 600 + 1000 * (req.PacketCounter - 1), im.ImageData.Data, 0, size);
                        req.RequestUser.OutPacket(im);
                        req.PacketCounter++;
                        //req.ImageInfo.last_used = time;
                        //System.Console.WriteLine("sent a packet of texture: "+req.image_info.FullID);
                    }
                }
            }

            //remove requests that have been completed
            int count = 0;

            for (int i = 0; i < num; i++)
            {
                if (this.TextureRequests.Count > count)
                {
                    req = (AssetRequest)this.TextureRequests[count];
                    if (req.PacketCounter == req.NumPackets)
                    {
                        this.TextureRequests.Remove(req);
                    }
                    else
                    {
                        count++;
                    }
                }
            }
        }