Example #1
0
        /// <summary>
        /// Request a download of this folder's content information.  Block until done, or timeout is reached
        /// </summary>
        /// <param name="recurse">Indicate if we should recursively download content information.</param>
        /// <param name="folders">Indicate if sub-folder data should be downloaded (true)</param>
        /// <param name="items">Indicate if item data should be downloaded too (true)</param>
        /// <param name="timeout">Milliseconds to wait before timing out, or -1 to wait indefinately.</param>
        /// <returns>The Request object for this download</returns>
        public DownloadRequest_Folder RequestDownloadContents(bool recurse, bool folders, bool items, int timeout)
        {
            DownloadRequest_Folder dr = iManager.FolderRequestAppend(FolderID, recurse, true, items, Name);

            dr.RequestComplete.WaitOne(timeout, false);
            return(dr);
        }
Example #2
0
        public override bool Equals(object obj)
        {
            if (obj is DownloadRequest_Folder)
            {
                DownloadRequest_Folder df = (DownloadRequest_Folder)obj;

                if ((this.FolderID == df.FolderID) &&
                    (this.Recurse == df.Recurse) &&
                    (this.FetchFolders == df.FetchFolders) &&
                    (this.FetchItems == df.FetchItems) &&
                    (this.Received == df.Received) &&
                    (this.Expected == df.Expected)
                    )
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                return(base.Equals(obj));
            }
        }
Example #3
0
        /// <summary>
        /// Request a download of this folder's content information.
        /// </summary>
        /// <param name="Recurse">Indicate if we should recursively download content information.</param>
        /// <param name="Items">Indicate if item data should be downloaded too (true), or only folders(false)</param>
        /// <returns>The Request object for this download</returns>
        public DownloadRequest_Folder RequestDownloadContents(bool recurse, bool items)
        {
            _Contents.Clear();

            DownloadRequest_Folder dr = new DownloadRequest_Folder(FolderID, recurse, items);

            iManager.RequestFolder(dr);

            return(dr);
        }
Example #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="dr"></param>
        internal void RequestFolder(DownloadRequest_Folder dr)
        {
            Packet packet = InvPacketHelper.FetchInventoryDescendents(
                dr.FolderID
                , dr.FetchFolders
                , dr.FetchItems);

            FolderDownloadStatus[dr.FolderID] = dr;

            slClient.Network.SendPacket(packet);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dr"></param>
        internal void RequestFolder(DownloadRequest_Folder dr)
        {
            Packet packet = InvPacketHelper.FetchInventoryDescendents(
                            dr.FolderID
                            , dr.FetchFolders
                            , dr.FetchItems);

            FolderDownloadStatus[dr.FolderID] = dr;

            slClient.Network.SendPacket(packet);
        }
Example #6
0
        /// <summary>
        /// If not currently downloading a request, dequeue the next request and start it.
        /// </summary>
        protected void FolderRequestBegin()
        {
            // Wait until it's safe to be modifying what is currently downloading.
            CurrentlyDownloadingMutex.WaitOne();

            // If we not already downloading stuff, then lets start
            if (CurrentlyDownloadingAFolder == false)
            {
                // Start downloading the first thing at the head of the queue
                lock (FolderRequests)
                {
                    while ((FolderRequests.Count > 0) && (FolderRequests[0].IsCompleted))
                    {
                        LogDescendantQueueEvent("Head request completed, notify recurse completed: " + FolderRequests[0]);
                        FolderRequests.RemoveAt(0);
                    }

                    if (FolderRequests.Count > 0)
                    {
                        CurrentlyDownloadingRequest = FolderRequests[0];
                        LogDescendantQueueEvent("Starting download of head of queue: " + FolderRequests[0].ToString());
                    }
                    else
                    {
                        // Nothing to do

                        // Release so that we can let other things look at and modify what is currently downloading.
                        CurrentlyDownloadingMutex.ReleaseMutex();

                        return;
                    }
                }

                // Mark that we're currently downloading
                CurrentlyDownloadingAFolder = true;

                // Download!
                Packet packet = InvPacketHelper.FetchInventoryDescendents(
                                CurrentlyDownloadingRequest.FolderID
                                , CurrentlyDownloadingRequest.FetchFolders
                                , CurrentlyDownloadingRequest.FetchItems);

                slClient.Network.SendPacket(packet);
            }

            // Release so that we can let other things look at and modify what is currently downloading.
            CurrentlyDownloadingMutex.ReleaseMutex();
        }
Example #7
0
        protected DownloadRequest_Folder FolderRequestPrepend(LLUUID folderID, bool recurse, bool fetchFolders, bool fetchItems, string requestName)
        {
            DownloadRequest_Folder dr = new DownloadRequest_Folder(folderID, recurse, fetchFolders, fetchItems, requestName);

            // Prepend the request at the head of the queue
            lock (FolderRequests)
            {
                if (FolderRequests.Contains(dr))
                {
                    foreach (DownloadRequest_Folder existing in FolderRequests)
                    {
                        if (dr.Equals(existing))
                        {
                            dr = existing;
                            break;
                        }
                    }

                    LogDescendantQueueEvent("Append(returned existing): " + dr.ToString());
                }
                else
                {
                    FolderRequests.Insert(0, dr);
                    LogDescendantQueueEvent("Prepend: " + dr.ToString());
                }
            }
            return dr;
        }
Example #8
0
        /// <summary>
        /// Append a request to the end of the queue.
        /// </summary>
        internal DownloadRequest_Folder FolderRequestAppend(LLUUID folderID, bool recurse, bool fetchFolders, bool fetchItems, string requestName)
        {

            DownloadRequest_Folder dr = new DownloadRequest_Folder(folderID, recurse, fetchFolders, fetchItems, requestName);

            // Add new request to the tail of the queue
            lock (FolderRequests)
            {
                if (FolderRequests.Contains(dr))
                {
                    foreach (DownloadRequest_Folder existing in FolderRequests)
                    {
                        if (dr.Equals(existing))
                        {
                            dr = existing;
                            break;
                        }
                    }
                    LogDescendantQueueEvent("Append(returned existing): " + dr.ToString());
                }
                else
                {
                    FolderRequests.Add(dr);
                    LogDescendantQueueEvent("Append: " + dr.ToString());
                }
            }

            FolderRequestBegin();
            return dr;
        }
Example #9
0
        /// <summary>
        /// Returned in response to a FetchInventoryDescendents request.  Contains information about the
        /// contents of a folder.
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="simulator"></param>
        public void InventoryDescendentsHandler(Packet packet, Simulator simulator)
        {
            InventoryDescendentsPacket reply = (InventoryDescendentsPacket)packet;

            // The UUID of this folder.
            LLUUID uuidFolderID = reply.AgentData.FolderID;

            // Wait until it's safe to be looking at what is currently downloading.
            CurrentlyDownloadingMutex.WaitOne();

            // Make sure this request matches the one we believe is the currently downloading request
            if (((CurrentlyDownloadingRequest != null) && (CurrentlyDownloadingRequest.FolderID != uuidFolderID)) || (CurrentlyDownloadingRequest == null))
            {
                // Release so that we can let other things look at and modify what is currently downloading.
                CurrentlyDownloadingMutex.ReleaseMutex();

                // Log problem
                LogDescendantQueueEvent("Unexpected descendent packet for folder: " + uuidFolderID.ToStringHyphenated());

                // Just discard this packet...
                return;
            }

            // Get the Inventory folder that we'll be updating
            InventoryFolder InvFolderUpdating = (InventoryFolder)FoldersByUUID[uuidFolderID];


            // Update Inventory Manager's last tick point, used for timeouts and such
//            LastPacketRecievedAtTick = Environment.TickCount;

            // Used to count the number of descendants received to see if we're finished or not.
            int iDescendentsExpected = reply.AgentData.Descendents;
            int iDescendentsReceivedThisBlock = 0;

            #region Handle Child Items
            foreach (InventoryDescendentsPacket.ItemDataBlock itemBlock in reply.ItemData)
            {
                // There is always an item block, even if there isn't any items
                // the "filler" block will not have a name
                if (itemBlock.Name.Length != 0)
                {
                    iDescendentsReceivedThisBlock++;

                    if (itemBlock.ItemID == LLUUID.Zero)
                    {
                        // this shouldn't ever happen, unless you've uploaded an invalid item
                        // to yourself while developping inventory code :-(
                    }
                    else
                    {
                        InventoryItem TempInvItem = new InventoryItem(this, itemBlock);

                        if (InvFolderUpdating._Contents.Contains(TempInvItem) == false)
                        {
                            #region Create an instance of the appriopriate Inventory class
                            if ((TempInvItem.InvType == 7) && (TempInvItem.Type == (sbyte)Asset.AssetType.Notecard))
                            {
                                InventoryItem temp = new InventoryNotecard(this, TempInvItem);
                                TempInvItem = temp;
                            }
                            if ((TempInvItem.InvType == 3) && (TempInvItem.Type == (sbyte)Asset.AssetType.Landmark))
                            {
                                InventoryItem temp = new InventoryLandmark(this, TempInvItem);
                                TempInvItem = temp;
                            }

                            if ((TempInvItem.InvType == 0) && (TempInvItem.Type == (sbyte)Asset.AssetType.Texture))
                            {
                                InventoryItem temp = new InventoryImage(this, TempInvItem);
                                TempInvItem = temp;
                            }

                            if ((TempInvItem.InvType == 10) && (TempInvItem.Type == (sbyte)Asset.AssetType.LSLText))
                            {
                                InventoryItem temp = new InventoryScript(this, TempInvItem);
                                TempInvItem = temp;
                            }

                            if ((TempInvItem.InvType == 18) &&
                                (
                                    (TempInvItem.Type == (sbyte)Asset.AssetType.Bodypart)
                                    || (TempInvItem.Type == (sbyte)Asset.AssetType.Clothing)
                                )
                               )
                            {
                                InventoryItem temp = new InventoryWearable(this, TempInvItem);
                                TempInvItem = temp;
                            }
                            #endregion

                            InvFolderUpdating._Contents.Add(TempInvItem);
                        }
                    }
                }
            }
            #endregion

            #region Handle Child Folders
            foreach (InventoryDescendentsPacket.FolderDataBlock folderBlock in reply.FolderData)
            {
                String IncomingName = System.Text.Encoding.UTF8.GetString(folderBlock.Name).Trim().Replace("\0", "");
                LLUUID IncomingFolderID = folderBlock.FolderID;
                LLUUID IncomingParentID = folderBlock.ParentID;
                sbyte IncomingType = folderBlock.Type;

                // There is always an folder block, even if there isn't any folders
                // the "filler" block will not have a name
                if (folderBlock.Name.Length != 0)
                {
                    iDescendentsReceivedThisBlock++;

                    // See if the Incoming Folder already exists locally
                    if (FoldersByUUID.ContainsKey(IncomingFolderID))
                    {
                        InventoryFolder existingFolder = FoldersByUUID[IncomingFolderID];
                        existingFolder._Name = IncomingName;
                        existingFolder._Type = IncomingType;

                        // Check if parent of existing is the same as the incoming
                        if (!existingFolder.ParentID.Equals(IncomingParentID))
                        {
                            // Remove existing from old parent
                            if (FoldersByUUID.ContainsKey(existingFolder.ParentID))
                            {
                                InventoryFolder ExistingParent = FoldersByUUID[existingFolder.ParentID];
                                if (ExistingParent._Contents.Contains(existingFolder))
                                {
                                    ExistingParent._Contents.Remove(existingFolder);
                                }
                            }

                            // Set existings parent to new
                            existingFolder._ParentID = IncomingParentID;

                            // Connect existing folder to parent specified in new
                            if (FoldersByUUID.ContainsKey(IncomingParentID))
                            {
                                InventoryFolder ExistingParent = FoldersByUUID[IncomingParentID];
                                if (!ExistingParent._Contents.Contains(existingFolder))
                                {
                                    ExistingParent._Contents.Add(existingFolder);
                                }
                            }
                        }
                    }
                    else
                    {
                        InventoryFolder TempInvFolder = new InventoryFolder(this, IncomingName, IncomingFolderID, IncomingParentID, IncomingType);

                        // Add folder to Parent
                        if (InvFolderUpdating._Contents.Contains(TempInvFolder) == false)
                        {
                            InvFolderUpdating._Contents.Add(TempInvFolder);
                        }

                        // Add folder to local cache lookup
                        FoldersByUUID[TempInvFolder.FolderID] = TempInvFolder;

                    }


                    // Do we recurse?
                    if (CurrentlyDownloadingRequest.Recurse)
                    {
                        // It's not the root, should be safe to "recurse"
                        if (!IncomingFolderID.Equals(slClient.Self.InventoryRootFolderUUID))
                        {
                            FolderRequestPrepend(IncomingFolderID, CurrentlyDownloadingRequest.Recurse, CurrentlyDownloadingRequest.FetchFolders, CurrentlyDownloadingRequest.FetchItems, CurrentlyDownloadingRequest.Name + "/" + IncomingName);
                        }
                    }
                }
            }
            #endregion

            // Update total number of descendants expected , and update the total downloaded
            CurrentlyDownloadingRequest.Expected = iDescendentsExpected;
            CurrentlyDownloadingRequest.Received += iDescendentsReceivedThisBlock;
            CurrentlyDownloadingRequest.LastReceivedAtTick = Environment.TickCount;

            if ((iDescendentsExpected > 1) && (iDescendentsReceivedThisBlock == 0))
            {
                slClient.Log("Received an InventoryDescendant packet where it indicated that there should be at least 1 descendant, but none were present... [" + CurrentlyDownloadingRequest.Name + "]", Helpers.LogLevel.Warning); 
                CurrentlyDownloadingRequest.Expected = 0;
            }

            if (LogDescendantQueue)
            {
                slClient.Log("Received packet for: " + CurrentlyDownloadingRequest.ToString(), Helpers.LogLevel.Info);
            }

            // Check if we're finished
            if (CurrentlyDownloadingRequest.Received >= CurrentlyDownloadingRequest.Expected)
            {
                LogDescendantQueueEvent("Done downloading request: " + CurrentlyDownloadingRequest);

                // Singal anyone that was waiting for this request to finish
                CurrentlyDownloadingRequest.RequestComplete.Set();

                // Raise an event for anyone that cares to listen for downloaded folder events
                if (OnRequestDownloadFinishedEvent != null)
                {
                    DownloadRequest_EventArgs e = new DownloadRequest_EventArgs();
                    e.DownloadRequest = CurrentlyDownloadingRequest;
                    FireRequestDownloadFinishedEvent(InvFolderUpdating, e);
                }

                // Set Inventory Manager state to reflect that we're done with the current download
                CurrentlyDownloadingAFolder = false;
                CurrentlyDownloadingRequest = null;
            }

            // Release so that we can let other things look at and modify what is currently downloading.
            CurrentlyDownloadingMutex.ReleaseMutex();


            // If there's any more download requests queued, grab one, and go
            FolderRequestBegin();
        }
        /// <summary>
        /// Request a download of this folder's content information.
        /// </summary>
        /// <param name="Recurse">Indicate if we should recursively download content information.</param>
        /// <param name="Items">Indicate if item data should be downloaded too (true), or only folders(false)</param>
        /// <returns>The Request object for this download</returns>
        public DownloadRequest_Folder RequestDownloadContents(bool recurse, bool items)
        {
            _Contents.Clear();

            DownloadRequest_Folder dr = new DownloadRequest_Folder(FolderID, recurse, items);
            iManager.RequestFolder(dr);

            return dr;
        }
Example #11
0
        /// <summary>
        /// Returned in response to a InventoryDescendantRequest.  Contains information about the
        /// contents of a folder.
        /// </summary>
        /// <seealso cref="InventoryManager.RequestFolder"/>
        /// <param name="packet"></param>
        /// <param name="simulator"></param>
        public void InventoryDescendentsHandler(Packet packet, Simulator simulator)
        {
            InventoryDescendentsPacket reply = (InventoryDescendentsPacket)packet;

            // The UUID of this folder.
            LLUUID uuidFolderID = reply.AgentData.FolderID;

            // Get the original Descendent Request for this Packet
            DownloadRequest_Folder dr = (DownloadRequest_Folder)FolderDownloadStatus[uuidFolderID];

            // Update Inventory Manager's last tick point, used for timeouts and such
            LastPacketRecievedAtTick = Environment.TickCount;

            // Some temp variables to be reused as we're parsing the packet
            InventoryItem   invItem;
            InventoryFolder invFolder;

            // Used to count the number of descendants received to see if we're finished or not.
            int iDescendentsExpected          = reply.AgentData.Descendents;
            int iDescendentsReceivedThisBlock = 0;



            foreach (InventoryDescendentsPacket.ItemDataBlock itemBlock in reply.ItemData)
            {
                // There is always an item block, even if there isn't any items
                // the "filler" block will not have a name
                if (itemBlock.Name.Length != 0)
                {
                    iDescendentsReceivedThisBlock++;

                    if (itemBlock.ItemID == LLUUID.Zero)
                    {
                        // this shouldn't ever happen, unless you've uploaded an invalid item
                        // to yourself while developping inventory code :-(
                    }
                    else
                    {
                        invItem = new InventoryItem(this, itemBlock);

                        InventoryFolder ifolder = (InventoryFolder)htFoldersByUUID[invItem.FolderID];

                        if (ifolder._Contents.Contains(invItem) == false)
                        {
                            if ((invItem.InvType == 7) && (invItem.Type == Asset.ASSET_TYPE_NOTECARD))
                            {
                                InventoryItem temp = new InventoryNotecard(this, invItem);
                                invItem = temp;
                            }

                            if ((invItem.InvType == 0) && (invItem.Type == Asset.ASSET_TYPE_IMAGE))
                            {
                                InventoryItem temp = new InventoryImage(this, invItem);
                                invItem = temp;
                            }

                            if ((invItem.InvType == 18) &&
                                (
                                    (invItem.Type == Asset.ASSET_TYPE_WEARABLE_BODY) ||
                                    (invItem.Type == Asset.ASSET_TYPE_WEARABLE_CLOTHING)
                                )
                                )

                            {
                                InventoryItem temp = new InventoryWearable(this, invItem);
                                invItem = temp;
                            }

                            ifolder._Contents.Add(invItem);
                        }
                    }
                }
            }


            foreach (InventoryDescendentsPacket.FolderDataBlock folderBlock in reply.FolderData)
            {
                String name     = System.Text.Encoding.UTF8.GetString(folderBlock.Name).Trim().Replace("\0", "");
                LLUUID folderid = folderBlock.FolderID;
                LLUUID parentid = folderBlock.ParentID;
// unused?      sbyte type = folderBlock.Type;

                // There is always an folder block, even if there isn't any folders
                // the "filler" block will not have a name
                if (folderBlock.Name.Length != 0)
                {
                    invFolder = new InventoryFolder(this, name, folderid, parentid);

                    iDescendentsReceivedThisBlock++;

                    // Add folder to Parent
                    InventoryFolder ifolder = (InventoryFolder)htFoldersByUUID[invFolder.ParentID];
                    if (ifolder._Contents.Contains(invFolder) == false)
                    {
                        ifolder._Contents.Add(invFolder);
                    }


                    // Add folder to UUID Lookup
                    htFoldersByUUID[invFolder.FolderID] = invFolder;


                    // Do we recurse?
                    if (dr.Recurse)
                    {
                        // It's not the root, should be safe to "recurse"
                        if (!invFolder.FolderID.Equals(slClient.Self.InventoryRootFolderUUID))
                        {
                            bool alreadyQueued = false;
                            foreach (DownloadRequest_Folder adr in alFolderRequestQueue)
                            {
                                if (adr.FolderID == invFolder.FolderID)
                                {
                                    alreadyQueued = true;
                                    break;
                                }
                            }

                            if (!alreadyQueued)
                            {
                                alFolderRequestQueue.Add(new DownloadRequest_Folder(invFolder.FolderID));
                            }
                        }
                    }
                }
            }



            // Update download status for this folder
            if (iDescendentsReceivedThisBlock >= iDescendentsExpected)
            {
                // We received all the descendents we're expecting for this folder
                // in this packet, so go ahead and remove folder from status list.
                FolderDownloadStatus.Remove(uuidFolderID);
                dr.RequestComplete.Set();
            }
            else
            {
                // This one packet didn't have all the descendents we're expecting
                // so update the total we're expecting, and update the total downloaded
                dr.Expected           = iDescendentsExpected;
                dr.Received          += iDescendentsReceivedThisBlock;
                dr.LastReceivedAtTick = Environment.TickCount;

                if (dr.Received >= dr.Expected)
                {
                    // Looks like after updating, we have all the descendents,
                    // remove from folder status.
                    FolderDownloadStatus.Remove(uuidFolderID);
                    dr.RequestComplete.Set();
                }
                else
                {
                    FolderDownloadStatus[uuidFolderID] = dr;
                }
            }
        }
Example #12
0
        public void DownloadInventory()
        {
            ClearState();

            if (FolderDownloadStatus == null)
            {
                // Create status table
                FolderDownloadStatus = new Dictionary <LLUUID, DownloadRequest_Folder>();
            }
            else
            {
                if (FolderDownloadStatus.Count != 0)
                {
                    throw new Exception("Inventory Download requested while previous download in progress.");
                }
            }

            if (alFolderRequestQueue == null)
            {
                alFolderRequestQueue = new List <DownloadRequest_Folder>();
            }

            // Set last packet received to now, just so out time-out timer works
            LastPacketRecievedAtTick = Environment.TickCount;

            // Send Packet requesting the root Folder,
            // this should recurse through all folders
            RequestFolder(new DownloadRequest_Folder(slClient.Self.InventoryRootFolderUUID));

            while ((FolderDownloadStatus.Count > 0) || (alFolderRequestQueue.Count > 0))
            {
                if (FolderDownloadStatus.Count == 0)
                {
                    DownloadRequest_Folder dr = alFolderRequestQueue[0];
                    alFolderRequestQueue.RemoveAt(0);
                    RequestFolder(dr);
                }

                int curTick = Environment.TickCount;
                if ((curTick - LastPacketRecievedAtTick) > 10000)
                {
                    slClient.Log("Time-out while waiting for packets (" +
                                 ((curTick - LastPacketRecievedAtTick) / 1000) + " seconds since last packet)",
                                 Helpers.LogLevel.Warning);

                    // have to make a seperate list otherwise we run into modifying the original array
                    // while still enumerating it.
                    List <DownloadRequest_Folder> alRestartList = new List <DownloadRequest_Folder>();


                    foreach (DownloadRequest_Folder dr in FolderDownloadStatus.Values)
                    {
                        alRestartList.Add(dr);
                    }

                    LastPacketRecievedAtTick = Environment.TickCount;
                    foreach (DownloadRequest_Folder dr in alRestartList)
                    {
                        RequestFolder(dr);
                    }
                }

                slClient.Tick();
            }
        }