// FIXME: these all should probably go into the respective region // modules // multiple fetch-folder maps are allowed within the larger folders map. public string FetchInventoryRequest(string request, string path, string param) { m_log.Debug("[Caps]: Inventory Request in region: " + m_regionName); Hashtable hash = new Hashtable(); try { hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); } catch (LLSD.LLSDParseException pe) { m_log.Error("[Agent Inventory]: Fetch error: " + pe.Message); m_log.Error("Request: " + request.ToString()); } ArrayList foldersrequested = (ArrayList)hash["folders"]; string response = ""; for (int i = 0; i < foldersrequested.Count; i++) { string inventoryitemstr = ""; Hashtable inventoryhash = (Hashtable)foldersrequested[i]; LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest); inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", ""); inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", ""); response += inventoryitemstr; } if (response.Length == 0) { // Ter-guess: If requests fail a lot, the client seems to stop requesting descendants. // Therefore, I'm concluding that the client only has so many threads available to do requests // and when a thread stalls.. is stays stalled. // Therefore we need to return something valid response = "<llsd><map><key>folders</key><array /></map></llsd>"; } else { response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>"; } return(response); }
/// <summary> /// Construct an LLSD reply packet to a CAPS inventory request /// </summary> /// <param name="invFetch"></param> /// <returns></returns> private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch) { LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); contents.agent_id = m_agentID; contents.owner_id = invFetch.owner_id; contents.folder_id = invFetch.folder_id; reply.folders.Array.Add(contents); InventoryCollection inv = new InventoryCollection(); inv.Folders = new List <InventoryFolderBase>(); inv.Items = new List <InventoryItemBase>(); int version = 0; if (CAPSFetchInventoryDescendents != null) { inv = CAPSFetchInventoryDescendents(m_agentID, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version); } if (inv.Folders != null) { foreach (InventoryFolderBase invFolder in inv.Folders) { contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); } } if (inv.Items != null) { foreach (InventoryItemBase invItem in inv.Items) { contents.items.Array.Add(ConvertInventoryItem(invItem)); } } contents.descendents = contents.items.Array.Count + contents.categories.Array.Count; contents.version = version; return(reply); }
/// <summary> /// Construct an LLSD reply packet to a CAPS inventory request /// </summary> /// <param name="invFetch"></param> /// <returns></returns> private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch) { LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); contents.agent_id = m_agentID; contents.owner_id = invFetch.owner_id; contents.folder_id = invFetch.folder_id; reply.folders.Array.Add(contents); InventoryCollection inv = new InventoryCollection(); inv.Folders = new List<InventoryFolderBase>(); inv.Items = new List<InventoryItemBase>(); int version = 0; if (CAPSFetchInventoryDescendents != null) { inv = CAPSFetchInventoryDescendents(m_agentID, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version); } if (inv.Folders != null) { foreach (InventoryFolderBase invFolder in inv.Folders) { contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); } } if (inv.Items != null) { foreach (InventoryItemBase invItem in inv.Items) { contents.items.Array.Add(ConvertInventoryItem(invItem)); } } contents.descendents = contents.items.Array.Count + contents.categories.Array.Count; contents.version = version; return reply; }
private LLSDInventoryDescendents ToLLSD(InventoryCollection inv, int descendents) { LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); contents.agent_id = inv.OwnerID; contents.owner_id = inv.OwnerID; contents.folder_id = inv.FolderID; reply.folders.Array.Add(contents); if (inv.Folders != null) { foreach (InventoryFolderBase invFolder in inv.Folders) { contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); } descendents += inv.Folders.Count; } if (inv.Items != null) { foreach (InventoryItemBase invItem in inv.Items) { contents.items.Array.Add(ConvertInventoryItem(invItem)); } } contents.descendents = descendents; contents.version = inv.Version; return reply; }
/// <summary> /// Construct an LLSD reply packet to a CAPS inventory request /// </summary> /// <param name="invFetch"></param> /// <returns></returns> private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch) { LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); contents.agent_id = invFetch.owner_id; contents.owner_id = invFetch.owner_id; contents.folder_id = invFetch.folder_id; reply.folders.Array.Add(contents); InventoryCollection inv = new InventoryCollection(); inv.Folders = new List<InventoryFolderBase>(); inv.Items = new List<InventoryItemBase>(); int version = 0; int descendents = 0; #pragma warning disable 0612 inv = Fetch( invFetch.owner_id, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents); #pragma warning restore 0612 if (inv != null && inv.Folders != null) { foreach (InventoryFolderBase invFolder in inv.Folders) { contents.categories.Array.Add(ConvertInventoryFolder(invFolder)); } descendents += inv.Folders.Count; } if (inv != null && inv.Items != null) { foreach (InventoryItemBase invItem in inv.Items) { contents.items.Array.Add(ConvertInventoryItem(invItem)); } } contents.descendents = descendents; contents.version = version; //m_log.DebugFormat( // "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}", // invFetch.folder_id, // invFetch.fetch_items, // invFetch.fetch_folders, // contents.items.Array.Count, // contents.categories.Array.Count, // invFetch.owner_id); return reply; }
public string FetchInventoryDescendentsRequest(string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { // nasty temporary hack here, the linden client falsely // identifies the uuid 00000000-0000-0000-0000-000000000000 // as a string which breaks us // // correctly mark it as a uuid request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>"); // another hack <integer>1</integer> results in a // System.ArgumentException: Object type System.Int32 cannot // be converted to target type: System.Boolean request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>"); request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>"); Hashtable hash = new Hashtable(); try { hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); } catch (LLSD.LLSDParseException pe) { m_log.Error("[Agent Inventory]: Fetch error: " + pe.Message); m_log.Error("Request: " + request.ToString()); } ArrayList foldersrequested = (ArrayList)hash["folders"]; string response = ""; lock (m_fetchLock) { for (int i = 0; i < foldersrequested.Count; i++) { string inventoryitemstr = ""; Hashtable inventoryhash = (Hashtable)foldersrequested[i]; LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); try { LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); } catch (Exception e) { m_log.Debug("[Caps]: caught exception doing OSD deserialize" + e); } LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest); inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", ""); inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", ""); response += inventoryitemstr; } if (response.Length == 0) { // Ter-guess: If requests fail a lot, the client seems to stop requesting descendants. // Therefore, I'm concluding that the client only has so many threads available to do requests // and when a thread stalls.. is stays stalled. // Therefore we need to return something valid response = "<llsd><map><key>folders</key><array /></map></llsd>"; } else { response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>"; } } return(response); }
/// <summary> /// Construct an LLSD reply packet to a CAPS inventory request /// </summary> /// <param name="invFetch"></param> /// <returns></returns> private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch) { LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); contents.agent_id = m_agentID; contents.owner_id = invFetch.owner_id; contents.folder_id = invFetch.folder_id; // The version number being sent back was originally 1. // Unfortunately, on 1.19.1.4, this means that we see a problem where on subsequent logins // without clearing client cache, objects in the root folder disappear until the cache is cleared, // at which point they reappear. // // Seeing the version to something other than 0 may be the right thing to do, but there is // a greater subtlety of the second life protocol that needs to be understood first. contents.version = 0; contents.descendents = 0; reply.folders.Array.Add(contents); List<InventoryItemBase> itemList = null; if (CAPSFetchInventoryDescendents != null) { itemList = CAPSFetchInventoryDescendents(m_agentID, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order); } if (itemList != null) { foreach (InventoryItemBase invItem in itemList) { contents.items.Array.Add(ConvertInventoryItem(invItem)); } } /* The following block is removed as it ALWAYS sends the error to the client because the RC 1.22.9 client tries to find items that have become dissasociated with a paret folder and have parent of 00000000-0000-00000.... else { IClientAPI client = GetClient(m_agentID); // We're going to both notify the client of inventory service failure and send back a 'no folder contents' response. // If we don't send back the response, // the client becomes unhappy (see Teravus' comment in FetchInventoryRequest()) if (client != null) { client.SendAgentAlertMessage( "AGIN0001E: The inventory service has either failed or is not responding. Your inventory will not function properly for the rest of this session. Please clear your cache and relog.", true); } else { m_log.ErrorFormat( "[AGENT INVENTORY]: Could not lookup controlling client for {0} in order to notify them of the inventory service failure", m_agentID); } }*/ contents.descendents = contents.items.Array.Count; return reply; }