123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- /*
- * 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 OpenSimulator 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 System;
- using System.IO;
- using System.Xml;
- using OpenSim.Region.ScriptEngine.Shared;
- using OpenSim.Region.ScriptEngine.Shared.Api;
- using log4net;
- using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
- using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
- using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
- using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
- using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
- using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
- using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
- namespace OpenSim.Region.ScriptEngine.Yengine
- {
- public partial class XMRInstance
- {
- /********************************************************************************\
- * The only method of interest to outside this module is GetExecutionState() *
- * which captures the current state of the script into an XML document. *
- * *
- * The rest of this module contains support routines for GetExecutionState(). *
- \********************************************************************************/
- /**
- * @brief Create an XML element that gives the current state of the script.
- * <ScriptState Engine="YEngine" SourceHash=m_ObjCode.sourceHash Asset=m_Item.AssetID>
- * <Snapshot>globalsandstackdump</Snapshot>
- * <Running>m_Running</Running>
- * <DetectArray ...
- * <EventQueue ...
- * <Permissions ...
- * <Plugins />
- * </ScriptState>
- * Updates the .state file while we're at it.
- */
- public XmlElement GetExecutionState(XmlDocument doc)
- {
- // When we're detaching an attachment, we need to wait here.
- // Change this to a 5 second timeout. If things do mess up,
- // we don't want to be stuck forever.
- //
- m_DetachReady.WaitOne(5000, false);
- XmlElement scriptStateN = doc.CreateElement("", "ScriptState", "");
- scriptStateN.SetAttribute("Engine", m_Engine.ScriptEngineName);
- scriptStateN.SetAttribute("Asset", m_Item.AssetID.ToString());
- scriptStateN.SetAttribute("SourceHash", m_ObjCode.sourceHash);
- // Make sure we aren't executing part of the script so it stays
- // stable. Setting suspendOnCheckRun tells CheckRun() to suspend
- // and return out so RunOne() will release the lock asap.
- suspendOnCheckRunHold = true;
- lock(m_RunLock)
- {
- m_RunOnePhase = "GetExecutionState enter";
- CheckRunLockInvariants(true);
- // Get copy of script globals and stack in relocateable form.
- Byte[] snapshotBytes;
- using (MemoryStream snapshotStream = new MemoryStream())
- {
- MigrateOutEventHandler(snapshotStream);
- snapshotBytes = snapshotStream.ToArray();
- }
- string snapshotString = Convert.ToBase64String(snapshotBytes);
- XmlElement snapshotN = doc.CreateElement("", "Snapshot", "");
- snapshotN.AppendChild(doc.CreateTextNode(snapshotString));
- scriptStateN.AppendChild(snapshotN);
- m_RunOnePhase = "GetExecutionState B";
- CheckRunLockInvariants(true);
- // "Running" says whether or not we are accepting new events.
- XmlElement runningN = doc.CreateElement("", "Running", "");
- runningN.AppendChild(doc.CreateTextNode(m_Running.ToString()));
- scriptStateN.AppendChild(runningN);
- m_RunOnePhase = "GetExecutionState C";
- CheckRunLockInvariants(true);
- // "DoGblInit" says whether or not default:state_entry() will init global vars.
- XmlElement doGblInitN = doc.CreateElement("", "DoGblInit", "");
- doGblInitN.AppendChild(doc.CreateTextNode(doGblInit.ToString()));
- scriptStateN.AppendChild(doGblInitN);
- m_RunOnePhase = "GetExecutionState D";
- CheckRunLockInvariants(true);
- // More misc data.
- XmlNode permissionsN = doc.CreateElement("", "Permissions", "");
- scriptStateN.AppendChild(permissionsN);
- XmlAttribute granterA = doc.CreateAttribute("", "granter", "");
- granterA.Value = m_Item.PermsGranter.ToString();
- permissionsN.Attributes.Append(granterA);
- XmlAttribute maskA = doc.CreateAttribute("", "mask", "");
- maskA.Value = m_Item.PermsMask.ToString();
- permissionsN.Attributes.Append(maskA);
- m_RunOnePhase = "GetExecutionState E";
- CheckRunLockInvariants(true);
- // "DetectParams" are returned by llDetected...() script functions
- // for the currently active event, if any.
- if(m_DetectParams != null)
- {
- XmlElement detParArrayN = doc.CreateElement("", "DetectArray", "");
- AppendXMLDetectArray(doc, detParArrayN, m_DetectParams);
- scriptStateN.AppendChild(detParArrayN);
- }
- m_RunOnePhase = "GetExecutionState F";
- CheckRunLockInvariants(true);
- // Save any events we have in the queue.
- // <EventQueue>
- // <Event Name="...">
- // <param>...</param> ...
- // <DetectParams>...</DetectParams> ...
- // </Event>
- // ...
- // </EventQueue>
- XmlElement queuedEventsN = doc.CreateElement("", "EventQueue", "");
- lock(m_QueueLock)
- {
- foreach(EventParams evt in m_EventQueue)
- {
- XmlElement singleEventN = doc.CreateElement("", "Event", "");
- singleEventN.SetAttribute("Name", evt.EventName);
- AppendXMLObjectArray(doc, singleEventN, evt.Params, "param");
- AppendXMLDetectArray(doc, singleEventN, evt.DetectParams);
- queuedEventsN.AppendChild(singleEventN);
- }
- }
- scriptStateN.AppendChild(queuedEventsN);
- m_RunOnePhase = "GetExecutionState G";
- CheckRunLockInvariants(true);
- // "Plugins" indicate enabled timers and listens, etc.
- Object[] pluginData =
- AsyncCommandManager.GetSerializationData(m_Engine, m_ItemID);
- XmlNode plugins = doc.CreateElement("", "Plugins", "");
- AppendXMLObjectArray(doc, plugins, pluginData, "plugin");
- scriptStateN.AppendChild(plugins);
- m_RunOnePhase = "GetExecutionState H";
- CheckRunLockInvariants(true);
- // Let script run again.
- suspendOnCheckRunHold = false;
- m_RunOnePhase = "GetExecutionState leave";
- CheckRunLockInvariants(true);
- }
- // scriptStateN represents the contents of the .state file so
- // write the .state file while we are here.
- using(FileStream fs = File.Create(m_StateFileName))
- {
- using(StreamWriter sw = new StreamWriter(fs))
- sw.Write(scriptStateN.OuterXml);
- }
- return scriptStateN;
- }
- /**
- * @brief Write script state to output stream.
- * Input:
- * stream = stream to write event handler state information to
- */
- private void MigrateOutEventHandler(Stream stream)
- {
- // Write script state out, frames and all, to the stream.
- // Does not change script state.
- stream.WriteByte(migrationVersion);
- stream.WriteByte((byte)16);
- this.MigrateOut(new BinaryWriter(stream));
- }
- /**
- * @brief Convert an DetectParams[] to corresponding XML.
- * DetectParams[] holds the values retrievable by llDetected...() for
- * a given event.
- */
- private static void AppendXMLDetectArray(XmlDocument doc, XmlElement parent, DetectParams[] detect)
- {
- foreach(DetectParams d in detect)
- {
- XmlElement detectParamsN = GetXMLDetect(doc, d);
- parent.AppendChild(detectParamsN);
- }
- }
- private static XmlElement GetXMLDetect(XmlDocument doc, DetectParams d)
- {
- XmlElement detectParamsN = doc.CreateElement("", "DetectParams", "");
- XmlAttribute d_key = doc.CreateAttribute("", "key", "");
- d_key.Value = d.Key.ToString();
- detectParamsN.Attributes.Append(d_key);
- XmlAttribute pos = doc.CreateAttribute("", "pos", "");
- pos.Value = d.OffsetPos.ToString();
- detectParamsN.Attributes.Append(pos);
- XmlAttribute d_linkNum = doc.CreateAttribute("", "linkNum", "");
- d_linkNum.Value = d.LinkNum.ToString();
- detectParamsN.Attributes.Append(d_linkNum);
- XmlAttribute d_group = doc.CreateAttribute("", "group", "");
- d_group.Value = d.Group.ToString();
- detectParamsN.Attributes.Append(d_group);
- XmlAttribute d_name = doc.CreateAttribute("", "name", "");
- d_name.Value = d.Name.ToString();
- detectParamsN.Attributes.Append(d_name);
- XmlAttribute d_owner = doc.CreateAttribute("", "owner", "");
- d_owner.Value = d.Owner.ToString();
- detectParamsN.Attributes.Append(d_owner);
- XmlAttribute d_position = doc.CreateAttribute("", "position", "");
- d_position.Value = d.Position.ToString();
- detectParamsN.Attributes.Append(d_position);
- XmlAttribute d_rotation = doc.CreateAttribute("", "rotation", "");
- d_rotation.Value = d.Rotation.ToString();
- detectParamsN.Attributes.Append(d_rotation);
- XmlAttribute d_type = doc.CreateAttribute("", "type", "");
- d_type.Value = d.Type.ToString();
- detectParamsN.Attributes.Append(d_type);
- XmlAttribute d_velocity = doc.CreateAttribute("", "velocity", "");
- d_velocity.Value = d.Velocity.ToString();
- detectParamsN.Attributes.Append(d_velocity);
- return detectParamsN;
- }
- /**
- * @brief Append elements of an array of objects to an XML parent.
- * @param doc = document the parent is part of
- * @param parent = parent to append the items to
- * @param array = array of objects
- * @param tag = <tag ..>...</tag> for each element
- */
- private static void AppendXMLObjectArray(XmlDocument doc, XmlNode parent, object[] array, string tag)
- {
- foreach(object o in array)
- {
- XmlElement element = GetXMLObject(doc, o, tag);
- parent.AppendChild(element);
- }
- }
- /**
- * @brief Get and XML representation of an object.
- * @param doc = document the tag will be put in
- * @param o = object to be represented
- * @param tag = <tag ...>...</tag>
- */
- private static XmlElement GetXMLObject(XmlDocument doc, object o, string tag)
- {
- XmlAttribute typ = doc.CreateAttribute("", "type", "");
- XmlElement n = doc.CreateElement("", tag, "");
- if(o is LSL_List)
- {
- typ.Value = "list";
- n.Attributes.Append(typ);
- AppendXMLObjectArray(doc, n, ((LSL_List)o).Data, "item");
- }
- else
- {
- typ.Value = o.GetType().ToString();
- n.Attributes.Append(typ);
- n.AppendChild(doc.CreateTextNode(o.ToString()));
- }
- return n;
- }
- }
- }
|