From 280a5cba8b6ab1566b1f5d2dae96e2f8402c8ab4 Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Mon, 24 Dec 2007 22:35:01 +0000 Subject: Prim inventory script saving phase 1. Create necessary CAPS structures for correctly accepting prim inventory script updates. No user functionality yet. Refactoring to follow. --- .../Framework/Communications/Capabilities/Caps.cs | 203 ++++++++++++++++++++- .../Communications/Capabilities/LLSDCapsDetails.cs | 2 +- .../LLSDTaskInventoryUploadComplete.cs | 50 +++++ .../Capabilities/LLSDTaskScriptUpdate.cs | 51 ++++++ .../Framework/Communications/UserManagerBase.cs | 2 +- .../Region/Environment/Scenes/Scene.Inventory.cs | 41 ++++- OpenSim/Region/Environment/Scenes/Scene.cs | 5 +- 7 files changed, 343 insertions(+), 11 deletions(-) create mode 100644 OpenSim/Framework/Communications/Capabilities/LLSDTaskInventoryUploadComplete.cs create mode 100644 OpenSim/Framework/Communications/Capabilities/LLSDTaskScriptUpdate.cs diff --git a/OpenSim/Framework/Communications/Capabilities/Caps.cs b/OpenSim/Framework/Communications/Capabilities/Caps.cs index eb678a0..a72abbe 100644 --- a/OpenSim/Framework/Communications/Capabilities/Caps.cs +++ b/OpenSim/Framework/Communications/Capabilities/Caps.cs @@ -42,21 +42,29 @@ namespace OpenSim.Region.Capabilities string inventoryType, string assetType); public delegate LLUUID UpdateItem(LLUUID itemID, byte[] data); + + public delegate LLUUID UpdateTaskScript(LLUUID itemID, LLUUID primID, bool isScriptRunning, byte[] data); public delegate void NewInventoryItem(LLUUID userID, InventoryItemBase item); public delegate LLUUID ItemUpdatedCallback(LLUUID userID, LLUUID itemID, byte[] data); + + public delegate LLUUID TaskScriptUpdatedCallback(LLUUID userID, LLUUID itemID, LLUUID primID, + bool isScriptRunning, byte[] data); public class Caps { private string m_httpListenerHostName; private uint m_httpListenPort; + private string m_capsObjectPath = "00001-"; private string m_requestPath = "0000/"; private string m_mapLayerPath = "0001/"; private string m_newInventory = "0002/"; //private string m_requestTexture = "0003/"; private string m_notecardUpdatePath = "0004/"; + private string m_notecardTaskUpdatePath = "0005/"; + //private string eventQueue = "0100/"; private BaseHttpServer m_httpListener; private LLUUID m_agentID; @@ -65,8 +73,11 @@ namespace OpenSim.Region.Capabilities private Queue m_capsEventQueue = new Queue(); private bool m_dumpAssetsToFile; + // These are callbacks which will be setup by the scene so that we can update scene data when we + // receive capability calls public NewInventoryItem AddNewInventoryItem = null; public ItemUpdatedCallback ItemUpdatedCall = null; + public TaskScriptUpdatedCallback TaskScriptUpdatedCall = null; public Caps(AssetCache assetCache, BaseHttpServer httpServer, string httpListen, uint httpPort, string capsPath, LLUUID agent, bool dumpAssetsToFile) @@ -100,9 +111,11 @@ namespace OpenSim.Region.Capabilities AddLegacyCapsHandler(m_httpListener, m_requestPath, CapsRequest); //AddLegacyCapsHandler(m_httpListener, m_requestTexture , RequestTexture); AddLegacyCapsHandler(m_httpListener, m_notecardUpdatePath, NoteCardAgentInventory); + AddLegacyCapsHandler(m_httpListener, m_notecardTaskUpdatePath, ScriptTaskInventory); } - catch + catch (Exception e) { + MainLog.Instance.Error("CAPS", e.ToString()); } } @@ -117,7 +130,7 @@ namespace OpenSim.Region.Capabilities } /// - /// + /// Construct a client response detailing all the capabilities this server can provide. /// /// /// @@ -131,7 +144,7 @@ namespace OpenSim.Region.Capabilities } /// - /// + /// Return an LLSDCapsDetails listing all the capabilities this server can provide /// /// protected LLSDCapsDetails GetCapabilities() @@ -144,7 +157,7 @@ namespace OpenSim.Region.Capabilities caps.NewFileAgentInventory = capsBaseUrl + m_newInventory; caps.UpdateNotecardAgentInventory = capsBaseUrl + m_notecardUpdatePath; caps.UpdateScriptAgentInventory = capsBaseUrl + m_notecardUpdatePath; - // caps.UpdateScriptTaskInventory = capsBaseUrl + m_requestTexture; + caps.UpdateScriptTaskInventory = capsBaseUrl + m_notecardTaskUpdatePath; return caps; } @@ -249,9 +262,65 @@ namespace OpenSim.Region.Capabilities } #endregion + + /// + /// Callback for a client request for an upload url for a script task + /// inventory update + /// + /// + /// + /// + /// + public string ScriptTaskInventory(string request, string path, string param) + { + try + { +// MainLog.Instance.Debug("CAPS", "request: {0}, path: {1}, param: {2}", request, path, param); + + Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Helpers.StringToField(request)); + LLSDTaskScriptUpdate llsdUpdateRequest = new LLSDTaskScriptUpdate(); + LLSDHelpers.DeserialiseLLSDMap(hash, llsdUpdateRequest); + + string capsBase = "/CAPS/" + m_capsObjectPath; + string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); + + TaskInventoryScriptUpdater uploader = + new TaskInventoryScriptUpdater( + llsdUpdateRequest.item_id, + llsdUpdateRequest.task_id, + llsdUpdateRequest.is_script_running, + capsBase + uploaderPath, + m_httpListener, + m_dumpAssetsToFile); + uploader.OnUpLoad += TaskScriptUpdated; + + m_httpListener.AddStreamHandler( + new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps)); + string uploaderURL = "http://" + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + capsBase + + uploaderPath; + + LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); + uploadResponse.uploader = uploaderURL; + uploadResponse.state = "upload"; + +// MainLog.Instance.Verbose( +// "CAPS", +// "ScriptTaskInventory response: {0}", +// LLSDHelpers.SerialiseLLSDReply(uploadResponse)); + + return LLSDHelpers.SerialiseLLSDReply(uploadResponse); + } + catch (Exception e) + { + MainLog.Instance.Error("CAPS", e.ToString()); + } + + return null; + } /// - /// + /// Callback for a client request for an upload url for a notecard (or script) + /// agent inventory update /// /// /// @@ -265,11 +334,10 @@ namespace OpenSim.Region.Capabilities LLSDHelpers.DeserialiseLLSDMap(hash, llsdRequest); string capsBase = "/CAPS/" + m_capsObjectPath; - LLUUID newInvItem = llsdRequest.item_id; string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); ItemUpdater uploader = - new ItemUpdater(newInvItem, capsBase + uploaderPath, m_httpListener, m_dumpAssetsToFile); + new ItemUpdater(llsdRequest.item_id, capsBase + uploaderPath, m_httpListener, m_dumpAssetsToFile); uploader.OnUpLoad += ItemUpdated; m_httpListener.AddStreamHandler( @@ -281,6 +349,8 @@ namespace OpenSim.Region.Capabilities uploadResponse.uploader = uploaderURL; uploadResponse.state = "upload"; + MainLog.Instance.Verbose("CAPS", "NoteCardAgentInventory response: {0}", LLSDHelpers.SerialiseLLSDReply(uploadResponse)); + return LLSDHelpers.SerialiseLLSDReply(uploadResponse); } @@ -368,12 +438,36 @@ namespace OpenSim.Region.Capabilities } } + /// + /// Called when new asset data for an agent inventory item update has been uploaded. + /// + /// Item to update + /// New asset data + /// public LLUUID ItemUpdated(LLUUID itemID, byte[] data) { if (ItemUpdatedCall != null) { return ItemUpdatedCall(m_agentID, itemID, data); } + + return LLUUID.Zero; + } + + /// + /// Called when new asset data for an agent inventory item update has been uploaded. + /// + /// Item to update + /// Prim containing item to update + /// Signals whether the script to update is currently running + /// New asset data + public LLUUID TaskScriptUpdated(LLUUID itemID, LLUUID primID, bool isScriptRunning, byte[] data) + { + if (TaskScriptUpdatedCall != null) + { + return TaskScriptUpdatedCall(m_agentID, itemID, primID, isScriptRunning, data); + } + return LLUUID.Zero; } @@ -452,6 +546,10 @@ namespace OpenSim.Region.Capabilities } } + /// + /// This class is a callback invoked when a client sends asset data to + /// an agent inventory notecard update url + /// public class ItemUpdater { public event UpdateItem OnUpLoad; @@ -514,5 +612,96 @@ namespace OpenSim.Region.Capabilities fs.Close(); } } + + /// + /// This class is a callback invoked when a client sends asset data to + /// a task inventory script update url + /// + public class TaskInventoryScriptUpdater + { + public event UpdateTaskScript OnUpLoad; + + private string uploaderPath = ""; + private LLUUID inventoryItemID; + private LLUUID primID; + private bool isScriptRunning; + private BaseHttpServer httpListener; + private bool m_dumpAssetToFile; + + public TaskInventoryScriptUpdater(LLUUID inventoryItemID, LLUUID primID, int isScriptRunning, + string path, BaseHttpServer httpServer, bool dumpAssetToFile) + { + m_dumpAssetToFile = dumpAssetToFile; + + this.inventoryItemID = inventoryItemID; + this.primID = primID; + + // This comes in over the packet as an integer, but actually appears to be treated as a bool + this.isScriptRunning = (0 == isScriptRunning ? false : true); + + uploaderPath = path; + httpListener = httpServer; + } + + /// + /// + /// + /// + /// + /// + /// + public string uploaderCaps(byte[] data, string path, string param) + { + try + { +// MainLog.Instance.Verbose( +// "CAPS", +// "TaskInventoryScriptUpdater received data: {0}, path: {1}, param: {2}", +// data, path, param); + + string res = ""; + LLSDTaskInventoryUploadComplete uploadComplete = new LLSDTaskInventoryUploadComplete(); + LLUUID assetID = LLUUID.Zero; + + if (OnUpLoad != null) + { + assetID = OnUpLoad(inventoryItemID, primID, isScriptRunning, data); + } + + uploadComplete.item_id = inventoryItemID; + uploadComplete.task_id = primID; + uploadComplete.state = "complete"; + + res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); + + httpListener.RemoveStreamHandler("POST", uploaderPath); + + if (m_dumpAssetToFile) + { + SaveAssetToFile("updatedtaskscript" + Util.RandomClass.Next(1, 1000) + ".dat", data); + } + +// MainLog.Instance.Verbose("CAPS", "TaskInventoryScriptUpdater.uploaderCaps res: {0}", res); + + return res; + } + catch (Exception e) + { + MainLog.Instance.Error("CAPS", e.ToString()); + } + + // XXX Maybe this should be some meaningful error packet + return null; + } + + private void SaveAssetToFile(string filename, byte[] data) + { + FileStream fs = File.Create(filename); + BinaryWriter bw = new BinaryWriter(fs); + bw.Write(data); + bw.Close(); + fs.Close(); + } + } } } diff --git a/OpenSim/Framework/Communications/Capabilities/LLSDCapsDetails.cs b/OpenSim/Framework/Communications/Capabilities/LLSDCapsDetails.cs index c50d0a9..dfb1683 100644 --- a/OpenSim/Framework/Communications/Capabilities/LLSDCapsDetails.cs +++ b/OpenSim/Framework/Communications/Capabilities/LLSDCapsDetails.cs @@ -38,7 +38,7 @@ namespace OpenSim.Region.Capabilities // public string ChatSessionRequest = ""; public string UpdateNotecardAgentInventory = ""; public string UpdateScriptAgentInventory = ""; - // public string UpdateScriptTaskInventory = ""; + public string UpdateScriptTaskInventory = ""; // public string ParcelVoiceInfoRequest = ""; public LLSDCapsDetails() diff --git a/OpenSim/Framework/Communications/Capabilities/LLSDTaskInventoryUploadComplete.cs b/OpenSim/Framework/Communications/Capabilities/LLSDTaskInventoryUploadComplete.cs new file mode 100644 index 0000000..3703efc --- /dev/null +++ b/OpenSim/Framework/Communications/Capabilities/LLSDTaskInventoryUploadComplete.cs @@ -0,0 +1,50 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +using libsecondlife; + +namespace OpenSim.Region.Capabilities +{ + [LLSDMap] + public class LLSDTaskInventoryUploadComplete + { + /// + /// The task inventory item that was updated + /// + public LLUUID item_id; + + /// + /// The task that was updated + /// + public LLUUID task_id; + + /// + /// State of the upload. So far have only even seen this set to "complete" + /// + public string state; + } +} diff --git a/OpenSim/Framework/Communications/Capabilities/LLSDTaskScriptUpdate.cs b/OpenSim/Framework/Communications/Capabilities/LLSDTaskScriptUpdate.cs new file mode 100644 index 0000000..6dcf2b5 --- /dev/null +++ b/OpenSim/Framework/Communications/Capabilities/LLSDTaskScriptUpdate.cs @@ -0,0 +1,51 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using libsecondlife; + +namespace OpenSim.Region.Capabilities +{ + [LLSDMap] + public class LLSDTaskScriptUpdate + { + /// + /// The item containing the script to update + /// + public LLUUID item_id; + + /// + /// The task containing the script + /// + public LLUUID task_id; + + /// + /// Signals whether the script is currently active + /// + public int is_script_running; + } +} diff --git a/OpenSim/Framework/Communications/UserManagerBase.cs b/OpenSim/Framework/Communications/UserManagerBase.cs index cc540e7..d946e00 100644 --- a/OpenSim/Framework/Communications/UserManagerBase.cs +++ b/OpenSim/Framework/Communications/UserManagerBase.cs @@ -260,7 +260,7 @@ namespace OpenSim.Framework.UserManagement /// The users loginrequest public void CreateAgent(UserProfileData profile, XmlRpcRequest request) { - Hashtable requestData = (Hashtable) request.Params[0]; + //Hashtable requestData = (Hashtable) request.Params[0]; UserAgentData agent = new UserAgentData(); diff --git a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs index 2d0ffd8..531e8de 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs @@ -74,6 +74,13 @@ namespace OpenSim.Region.Environment.Scenes return LLUUID.Zero; } + /// + /// Capability originating call to update the asset of an item in an agent's inventory + /// + /// + /// + /// + /// public LLUUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, LLUUID itemID, byte[] data) { CachedUserInfo userInfo = CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); @@ -106,6 +113,39 @@ namespace OpenSim.Region.Environment.Scenes } return LLUUID.Zero; } + + /// + /// Capability originating call to update the asset of a script in a prim's (task's) inventory + /// + /// + /// + /// The prim which contains the item to update + /// Indicates whether the script to update is currently running + /// + /// Asset LLUID created + public LLUUID CapsUpdateTaskInventoryScriptAsset(LLUUID avatarID, LLUUID itemID, + LLUUID primID, bool isScriptRunning, byte[] data) + { + // TODO Not currently doing anything with the isScriptRunning bool + + MainLog.Instance.Verbose( + "PRIMINVENTORY", + "Prim inventory script save functionality not yet implemented." + + " remoteClient: {0}, itemID: {1}, primID: {2}, isScriptRunning: {3}", + avatarID, itemID, primID, isScriptRunning); + + // TODO + // Retrieve client LLUID + // Retrieve sog containing primID + // Retrieve item + // Create new asset and add to cache + // Update item with new asset + // Trigger SOG update (see RezScript) + // Trigger rerunning of script (use TriggerRezScript event, see RezScript) + // return new asset id + + return null; + } /// /// Update an item which is either already in the client's inventory or is within @@ -470,7 +510,6 @@ namespace OpenSim.Region.Environment.Scenes if (rezAsset != null) { string script = Util.FieldToString(rezAsset.Data); - //Console.WriteLine("rez script "+script); EventManager.TriggerRezScript(localID, copyID, script); rezzed = true; } diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index cf17686..2a25316 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -1350,10 +1350,13 @@ namespace OpenSim.Region.Environment.Scenes agent.CapsPath, agent.AgentID, m_dumpAssetsToFile); Util.SetCapsURL(agent.AgentID, "http://" + m_regInfo.ExternalHostName + ":" + httpListener.Port.ToString() + - "/CAPS/" + agent.CapsPath + "0000/"); + "/CAPS/" + agent.CapsPath + "0000/"); cap.RegisterHandlers(); + cap.AddNewInventoryItem = AddInventoryItem; cap.ItemUpdatedCall = CapsUpdateInventoryItemAsset; + cap.TaskScriptUpdatedCall = CapsUpdateTaskInventoryScriptAsset; + if (m_capsHandlers.ContainsKey(agent.AgentID)) { //MainLog.Instance.Warn("client", "Adding duplicate CAPS entry for user " + -- cgit v1.1