/// <summary>Check the queue for pending work</summary>
        private void EnqueuePending()
        {
            lock (queue)
            {
                if (queue.Count > 0)
                {
                    int nr = 0;
                    lock (activeDownloads) nr = activeDownloads.Count;

                    for (int i = nr; i < ParallelDownloads && queue.Count > 0; i++)
                    {
                        DownloadRequest item = queue.Dequeue();
                        Logger.DebugLog("Requesting " + item.Address.ToString());
                        HttpWebRequest req = SetupRequest(item.Address, item.ContentType);
                        CapsBase.DownloadDataAsync(
                            req,
                            item.MillisecondsTimeout,
                            item.DownloadProgressCallback,
                            (HttpWebRequest request, HttpWebResponse response, byte[] responseData, Exception error) =>
                        {
                            lock (activeDownloads) activeDownloads.Remove(request);
                            item.CompletedCallback(request, response, responseData, error);
                            EnqueuePending();
                        }
                            );

                        lock (activeDownloads) activeDownloads.Add(req);
                    }
                }
            }
        }
 /// <summary>Enqueue a new HTPP download</summary>
 public void QueueDownlad(DownloadRequest req)
 {
     lock (queue)
     {
         queue.Enqueue(req);
     }
     EnqueuePending();
 }
        /// <summary>Enqueue a new HTPP download</summary>
        public void QueueDownlad(DownloadRequest req)
        {
            lock (activeDownloads)
            {
                string addr = req.Address.ToString();
                if (activeDownloads.ContainsKey(addr))
                {
                    activeDownloads[addr].CompletedHandlers.Add(req.CompletedCallback);
                    if (req.DownloadProgressCallback != null)
                    {
                        activeDownloads[addr].ProgresHadlers.Add(req.DownloadProgressCallback);
                    }
                    return;
                }
            }

            lock (queue)
            {
                queue.Enqueue(req);
            }
            EnqueuePending();
        }
        /// <summary>
        /// Fetach avatar texture on a grid capable of server side baking
        /// </summary>
        /// <param name="avatarID">ID of the avatar</param>
        /// <param name="textureID">ID of the texture</param>
        /// <param name="bakeName">Name of the part of the avatar texture applies to</param>
        /// <param name="callback">Callback invoked on operation completion</param>
        public void RequestServerBakedImage(UUID avatarID, UUID textureID, string bakeName, TextureDownloadCallback callback)
        {
            if (avatarID == UUID.Zero || textureID == UUID.Zero || callback == null)
                return;

            if (string.IsNullOrEmpty(Client.Network.AgentAppearanceServiceURL))
            {
                callback(TextureRequestState.NotFound, null);
                return;
            }

            byte[] assetData;
            // Do we have this image in the cache?
            if (Client.Assets.Cache.HasAsset(textureID)
                && (assetData = Client.Assets.Cache.GetCachedAssetBytes(textureID)) != null)
            {
                ImageDownload image = new ImageDownload();
                image.ID = textureID;
                image.AssetData = assetData;
                image.Size = image.AssetData.Length;
                image.Transferred = image.AssetData.Length;
                image.ImageType = ImageType.ServerBaked;
                image.AssetType = AssetType.Texture;
                image.Success = true;

                callback(TextureRequestState.Finished, new AssetTexture(image.ID, image.AssetData));
                FireImageProgressEvent(image.ID, image.Transferred, image.Size);
                return;
            }

            CapsBase.DownloadProgressEventHandler progressHandler = null;

            Uri url = new Uri(string.Format("{0}texture/{1}/{2}/{3}", Client.Network.AgentAppearanceServiceURL, avatarID, bakeName, textureID));

            DownloadRequest req = new DownloadRequest(
                url,
                Client.Settings.CAPS_TIMEOUT,
                "image/x-j2c",
                progressHandler,
                (HttpWebRequest request, HttpWebResponse response, byte[] responseData, Exception error) =>
                {
                    if (error == null && responseData != null) // success
                    {
                        ImageDownload image = new ImageDownload();
                        image.ID = textureID;
                        image.AssetData = responseData;
                        image.Size = image.AssetData.Length;
                        image.Transferred = image.AssetData.Length;
                        image.ImageType = ImageType.ServerBaked;
                        image.AssetType = AssetType.Texture;
                        image.Success = true;

                        callback(TextureRequestState.Finished, new AssetTexture(image.ID, image.AssetData));

                        Client.Assets.Cache.SaveAssetToCache(textureID, responseData);
                    }
                    else // download failed
                    {
                        Logger.Log(
                            string.Format("Failed to fetch server bake {0}: {1}",
                                textureID,
                                (error == null) ? "" : error.Message
                            ),
                            Helpers.LogLevel.Warning, Client);

                        callback(TextureRequestState.Timeout, null);
                    }
                }
            );

            HttpDownloads.QueueDownload(req);
        }
        /// <summary>
        /// Requests download of a mesh asset
        /// </summary>
        /// <param name="meshID">UUID of the mesh asset</param>
        /// <param name="callback">Callback when the request completes</param>
        public void RequestMesh(UUID meshID, MeshDownloadCallback callback)
        {
            if (meshID == UUID.Zero || callback == null)
                return;

            if (Client.Network.CurrentSim.Caps != null &&
                Client.Network.CurrentSim.Caps.CapabilityURI("GetMesh") != null)
            {
                // Do we have this mesh asset in the cache?
                if (Client.Assets.Cache.HasAsset(meshID))
                {
                    callback(true, new AssetMesh(meshID, Client.Assets.Cache.GetCachedAssetBytes(meshID)));
                    return;
                }

                Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("GetMesh");

                DownloadRequest req = new DownloadRequest(
                    new Uri(string.Format("{0}/?mesh_id={1}", url.ToString(), meshID.ToString())),
                    Client.Settings.CAPS_TIMEOUT,
                    null,
                    null,
                    (HttpWebRequest request, HttpWebResponse response, byte[] responseData, Exception error) =>
                    {
                        if (error == null && responseData != null) // success
                        {
                            callback(true, new AssetMesh(meshID, responseData));
                            Client.Assets.Cache.SaveAssetToCache(meshID, responseData);
                        }
                        else // download failed
                        {
                            Logger.Log(
                                string.Format("Failed to fetch mesh asset {0}: {1}",
                                    meshID,
                                    (error == null) ? "" : error.Message
                                ),
                                Helpers.LogLevel.Warning, Client);
                        }
                    }
                );

                HttpDownloads.QueueDownload(req);
            }
            else
            {
                Logger.Log("GetMesh capability not available", Helpers.LogLevel.Error, Client);
                callback(false, null);
            }
        }
        // Helper method for downloading textures via GetTexture cap
        // Same signature as the UDP variant since we need all the params to
        // pass to the UDP TexturePipeline in case we need to fall back to it
        // (Linden servers currently (1.42) don't support bakes downloads via HTTP)
        private void HttpRequestTexture(UUID textureID, ImageType imageType, float priority, int discardLevel,
            uint packetStart, TextureDownloadCallback callback, bool progress)
        {
            if (textureID == UUID.Zero || callback == null)
                return;

            byte[] assetData;
            // Do we have this image in the cache?
            if (Client.Assets.Cache.HasAsset(textureID)
                && (assetData = Client.Assets.Cache.GetCachedAssetBytes(textureID)) != null)
            {
                ImageDownload image = new ImageDownload();
                image.ID = textureID;
                image.AssetData = assetData;
                image.Size = image.AssetData.Length;
                image.Transferred = image.AssetData.Length;
                image.ImageType = imageType;
                image.AssetType = AssetType.Texture;
                image.Success = true;

                callback(TextureRequestState.Finished, new AssetTexture(image.ID, image.AssetData));
                FireImageProgressEvent(image.ID, image.Transferred, image.Size);
                return;
            }

            CapsBase.DownloadProgressEventHandler progressHandler = null;

            if (progress)
            {
                progressHandler = (HttpWebRequest request, HttpWebResponse response, int bytesReceived, int totalBytesToReceive) =>
                    {
                        FireImageProgressEvent(textureID, bytesReceived, totalBytesToReceive);
                    };
            }

            Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("GetTexture");

            DownloadRequest req = new DownloadRequest(
                new Uri(string.Format("{0}/?texture_id={1}", url.ToString(), textureID.ToString())),
                Client.Settings.CAPS_TIMEOUT,
                "image/x-j2c",
                progressHandler,
                (HttpWebRequest request, HttpWebResponse response, byte[] responseData, Exception error) =>
                {
                    if (error == null && responseData != null) // success
                    {
                        ImageDownload image = new ImageDownload();
                        image.ID = textureID;
                        image.AssetData = responseData;
                        image.Size = image.AssetData.Length;
                        image.Transferred = image.AssetData.Length;
                        image.ImageType = imageType;
                        image.AssetType = AssetType.Texture;
                        image.Success = true;

                        callback(TextureRequestState.Finished, new AssetTexture(image.ID, image.AssetData));
                        FireImageProgressEvent(image.ID, image.Transferred, image.Size);

                        Client.Assets.Cache.SaveAssetToCache(textureID, responseData);
                    }
                    else // download failed
                    {
                        Logger.Log(
                            string.Format("Failed to fetch texture {0} over HTTP, falling back to UDP: {1}",
                                textureID,
                                (error == null) ? "" : error.Message
                            ),
                            Helpers.LogLevel.Warning, Client);

                        Texture.RequestTexture(textureID, imageType, priority, discardLevel, packetStart, callback, progress);
                    }
                }
            );

            HttpDownloads.QueueDownload(req);
        }
        /// <summary>Check the queue for pending work</summary>
        private void EnqueuePending()
        {
            lock (queue)
            {
                if (queue.Count > 0)
                {
                    int nr = 0;
                    lock (activeDownloads)
                    {
                        nr = activeDownloads.Count;
                    }

                    Logger.DebugLog(nr.ToString() + " active downloads. Queued textures: " + queue.Count.ToString());

                    for (int i = nr; i < ParallelDownloads && queue.Count > 0; i++)
                    {
                        DownloadRequest item = queue.Dequeue();
                        lock (activeDownloads)
                        {
                            string addr = item.Address.ToString();
                            if (activeDownloads.ContainsKey(addr))
                            {
                                activeDownloads[addr].CompletedHandlers.Add(item.CompletedCallback);
                                if (item.DownloadProgressCallback != null)
                                {
                                    activeDownloads[addr].ProgresHadlers.Add(item.DownloadProgressCallback);
                                }
                            }
                            else
                            {
                                ActiveDownload activeDownload = new ActiveDownload();
                                activeDownload.CompletedHandlers.Add(item.CompletedCallback);
                                if (item.DownloadProgressCallback != null)
                                {
                                    activeDownload.ProgresHadlers.Add(item.DownloadProgressCallback);
                                }

                                Logger.DebugLog("Requesting " + item.Address.ToString());
                                activeDownload.Request = SetupRequest(item.Address, item.ContentType);
                                CapsBase.DownloadDataAsync(
                                    activeDownload.Request,
                                    item.MillisecondsTimeout,
                                    (HttpWebRequest request, HttpWebResponse response, int bytesReceived, int totalBytesToReceive) =>
                                {
                                    foreach (CapsBase.DownloadProgressEventHandler handler in activeDownload.ProgresHadlers)
                                    {
                                        handler(request, response, bytesReceived, totalBytesToReceive);
                                    }
                                },
                                    (HttpWebRequest request, HttpWebResponse response, byte[] responseData, Exception error) =>
                                {
                                    lock (activeDownloads) activeDownloads.Remove(addr);
                                    if (error == null || item.Attempt >= item.Retries || (error != null && error.Message.Contains("404")))
                                    {
                                        foreach (CapsBase.RequestCompletedEventHandler handler in activeDownload.CompletedHandlers)
                                        {
                                            handler(request, response, responseData, error);
                                        }
                                    }
                                    else
                                    {
                                        item.Attempt++;
                                        Logger.Log(string.Format("Texture {0} HTTP download failed, trying again retry {1}/{2}",
                                                                 item.Address, item.Attempt, item.Retries), Helpers.LogLevel.Warning);
                                        lock (queue) queue.Enqueue(item);
                                    }

                                    EnqueuePending();
                                }
                                    );

                                activeDownloads[addr] = activeDownload;
                            }
                        }
                    }
                }
            }
        }
 /// <summary>Enqueue a new HTPP download</summary>
 public void QueueDownlad(DownloadRequest req)
 {
     lock (queue)
     {
         queue.Enqueue(req);
     }
     EnqueuePending();
 }
        /// <summary>Enqueue a new HTTP download</summary>
        public void QueueDownload(DownloadRequest req)
        {
            lock (activeDownloads)
            {
                string addr = req.Address.ToString();
                if (activeDownloads.ContainsKey(addr))
                {
                    activeDownloads[addr].CompletedHandlers.Add(req.CompletedCallback);
                    if (req.DownloadProgressCallback != null)
                    {
                        activeDownloads[addr].ProgresHadlers.Add(req.DownloadProgressCallback);
                    }
                    return;
                }
            }

            lock (queue)
            {
                queue.Enqueue(req);
            }
            EnqueuePending();
        }
Exemple #10
0
        /// <summary>Check the queue for pending work</summary>
        private void EnqueuePending()
        {
            lock (queue)
            {
                if (queue.Count > 0)
                {
                    int nr = 0;
                    lock (activeDownloads)
                    {
                        nr = activeDownloads.Count;
                    }

                    for (int i = nr; i < ParallelDownloads && queue.Count > 0; i++)
                    {
                        DownloadRequest item = queue.Dequeue();
                        lock (activeDownloads)
                        {
                            string addr = item.Address.ToString();
                            if (activeDownloads.ContainsKey(addr))
                            {
                                activeDownloads[addr].CompletedHandlers.Add(item.CompletedCallback);
                                if (item.DownloadProgressCallback != null)
                                {
                                    activeDownloads[addr].ProgresHadlers.Add(item.DownloadProgressCallback);
                                }
                            }
                            else
                            {
                                ActiveDownload activeDownload = new ActiveDownload();
                                activeDownload.CompletedHandlers.Add(item.CompletedCallback);
                                if (item.DownloadProgressCallback != null)
                                {
                                    activeDownload.ProgresHadlers.Add(item.DownloadProgressCallback);
                                }

                                Logger.DebugLog("Requesting " + item.Address.ToString());
                                activeDownload.Request = SetupRequest(item.Address, item.ContentType);
                                CapsBase.DownloadDataAsync(
                                    activeDownload.Request,
                                    item.MillisecondsTimeout,
                                    (HttpWebRequest request, HttpWebResponse response, int bytesReceived, int totalBytesToReceive) =>
                                {
                                    foreach (CapsBase.DownloadProgressEventHandler handler in activeDownload.ProgresHadlers)
                                    {
                                        handler(request, response, bytesReceived, totalBytesToReceive);
                                    }
                                },
                                    (HttpWebRequest request, HttpWebResponse response, byte[] responseData, Exception error) =>
                                {
                                    lock (activeDownloads) activeDownloads.Remove(addr);
                                    foreach (CapsBase.RequestCompletedEventHandler handler in activeDownload.CompletedHandlers)
                                    {
                                        handler(request, response, responseData, error);
                                    }
                                    EnqueuePending();
                                }
                                    );

                                activeDownloads[addr] = activeDownload;
                            }
                        }
                    }
                }
            }
        }