1
0

XMRInstCapture.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.IO;
  29. using System.Xml;
  30. using OpenSim.Region.ScriptEngine.Shared;
  31. using OpenSim.Region.ScriptEngine.Shared.Api;
  32. using log4net;
  33. using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
  34. using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
  35. using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  36. using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
  37. using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
  38. using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  39. using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
  40. namespace OpenSim.Region.ScriptEngine.Yengine
  41. {
  42. public partial class XMRInstance
  43. {
  44. /********************************************************************************\
  45. * The only method of interest to outside this module is GetExecutionState() *
  46. * which captures the current state of the script into an XML document. *
  47. * *
  48. * The rest of this module contains support routines for GetExecutionState(). *
  49. \********************************************************************************/
  50. /**
  51. * @brief Create an XML element that gives the current state of the script.
  52. * <ScriptState Engine="YEngine" SourceHash=m_ObjCode.sourceHash Asset=m_Item.AssetID>
  53. * <Snapshot>globalsandstackdump</Snapshot>
  54. * <Running>m_Running</Running>
  55. * <DetectArray ...
  56. * <EventQueue ...
  57. * <Permissions ...
  58. * <Plugins />
  59. * </ScriptState>
  60. * Updates the .state file while we're at it.
  61. */
  62. public XmlElement GetExecutionState(XmlDocument doc)
  63. {
  64. // When we're detaching an attachment, we need to wait here.
  65. // Change this to a 5 second timeout. If things do mess up,
  66. // we don't want to be stuck forever.
  67. //
  68. m_DetachReady.WaitOne(5000, false);
  69. XmlElement scriptStateN = doc.CreateElement("", "ScriptState", "");
  70. scriptStateN.SetAttribute("Engine", m_Engine.ScriptEngineName);
  71. scriptStateN.SetAttribute("Asset", m_Item.AssetID.ToString());
  72. scriptStateN.SetAttribute("SourceHash", m_ObjCode.sourceHash);
  73. // Make sure we aren't executing part of the script so it stays
  74. // stable. Setting suspendOnCheckRun tells CheckRun() to suspend
  75. // and return out so RunOne() will release the lock asap.
  76. suspendOnCheckRunHold = true;
  77. lock(m_RunLock)
  78. {
  79. m_RunOnePhase = "GetExecutionState enter";
  80. CheckRunLockInvariants(true);
  81. // Get copy of script globals and stack in relocateable form.
  82. MemoryStream snapshotStream = new MemoryStream();
  83. MigrateOutEventHandler(snapshotStream);
  84. Byte[] snapshotBytes = snapshotStream.ToArray();
  85. snapshotStream.Close();
  86. string snapshotString = Convert.ToBase64String(snapshotBytes);
  87. XmlElement snapshotN = doc.CreateElement("", "Snapshot", "");
  88. snapshotN.AppendChild(doc.CreateTextNode(snapshotString));
  89. scriptStateN.AppendChild(snapshotN);
  90. m_RunOnePhase = "GetExecutionState B";
  91. CheckRunLockInvariants(true);
  92. // "Running" says whether or not we are accepting new events.
  93. XmlElement runningN = doc.CreateElement("", "Running", "");
  94. runningN.AppendChild(doc.CreateTextNode(m_Running.ToString()));
  95. scriptStateN.AppendChild(runningN);
  96. m_RunOnePhase = "GetExecutionState C";
  97. CheckRunLockInvariants(true);
  98. // "DoGblInit" says whether or not default:state_entry() will init global vars.
  99. XmlElement doGblInitN = doc.CreateElement("", "DoGblInit", "");
  100. doGblInitN.AppendChild(doc.CreateTextNode(doGblInit.ToString()));
  101. scriptStateN.AppendChild(doGblInitN);
  102. m_RunOnePhase = "GetExecutionState D";
  103. CheckRunLockInvariants(true);
  104. // More misc data.
  105. XmlNode permissionsN = doc.CreateElement("", "Permissions", "");
  106. scriptStateN.AppendChild(permissionsN);
  107. XmlAttribute granterA = doc.CreateAttribute("", "granter", "");
  108. granterA.Value = m_Item.PermsGranter.ToString();
  109. permissionsN.Attributes.Append(granterA);
  110. XmlAttribute maskA = doc.CreateAttribute("", "mask", "");
  111. maskA.Value = m_Item.PermsMask.ToString();
  112. permissionsN.Attributes.Append(maskA);
  113. m_RunOnePhase = "GetExecutionState E";
  114. CheckRunLockInvariants(true);
  115. // "DetectParams" are returned by llDetected...() script functions
  116. // for the currently active event, if any.
  117. if(m_DetectParams != null)
  118. {
  119. XmlElement detParArrayN = doc.CreateElement("", "DetectArray", "");
  120. AppendXMLDetectArray(doc, detParArrayN, m_DetectParams);
  121. scriptStateN.AppendChild(detParArrayN);
  122. }
  123. m_RunOnePhase = "GetExecutionState F";
  124. CheckRunLockInvariants(true);
  125. // Save any events we have in the queue.
  126. // <EventQueue>
  127. // <Event Name="...">
  128. // <param>...</param> ...
  129. // <DetectParams>...</DetectParams> ...
  130. // </Event>
  131. // ...
  132. // </EventQueue>
  133. XmlElement queuedEventsN = doc.CreateElement("", "EventQueue", "");
  134. lock(m_QueueLock)
  135. {
  136. foreach(EventParams evt in m_EventQueue)
  137. {
  138. XmlElement singleEventN = doc.CreateElement("", "Event", "");
  139. singleEventN.SetAttribute("Name", evt.EventName);
  140. AppendXMLObjectArray(doc, singleEventN, evt.Params, "param");
  141. AppendXMLDetectArray(doc, singleEventN, evt.DetectParams);
  142. queuedEventsN.AppendChild(singleEventN);
  143. }
  144. }
  145. scriptStateN.AppendChild(queuedEventsN);
  146. m_RunOnePhase = "GetExecutionState G";
  147. CheckRunLockInvariants(true);
  148. // "Plugins" indicate enabled timers and listens, etc.
  149. Object[] pluginData =
  150. AsyncCommandManager.GetSerializationData(m_Engine, m_ItemID);
  151. XmlNode plugins = doc.CreateElement("", "Plugins", "");
  152. AppendXMLObjectArray(doc, plugins, pluginData, "plugin");
  153. scriptStateN.AppendChild(plugins);
  154. m_RunOnePhase = "GetExecutionState H";
  155. CheckRunLockInvariants(true);
  156. // Let script run again.
  157. suspendOnCheckRunHold = false;
  158. m_RunOnePhase = "GetExecutionState leave";
  159. CheckRunLockInvariants(true);
  160. }
  161. // scriptStateN represents the contents of the .state file so
  162. // write the .state file while we are here.
  163. FileStream fs = File.Create(m_StateFileName);
  164. StreamWriter sw = new StreamWriter(fs);
  165. sw.Write(scriptStateN.OuterXml);
  166. sw.Close();
  167. fs.Close();
  168. return scriptStateN;
  169. }
  170. /**
  171. * @brief Write script state to output stream.
  172. * Input:
  173. * stream = stream to write event handler state information to
  174. */
  175. private void MigrateOutEventHandler(Stream stream)
  176. {
  177. // Write script state out, frames and all, to the stream.
  178. // Does not change script state.
  179. stream.WriteByte(migrationVersion);
  180. stream.WriteByte((byte)16);
  181. this.MigrateOut(new BinaryWriter(stream));
  182. }
  183. /**
  184. * @brief Convert an DetectParams[] to corresponding XML.
  185. * DetectParams[] holds the values retrievable by llDetected...() for
  186. * a given event.
  187. */
  188. private static void AppendXMLDetectArray(XmlDocument doc, XmlElement parent, DetectParams[] detect)
  189. {
  190. foreach(DetectParams d in detect)
  191. {
  192. XmlElement detectParamsN = GetXMLDetect(doc, d);
  193. parent.AppendChild(detectParamsN);
  194. }
  195. }
  196. private static XmlElement GetXMLDetect(XmlDocument doc, DetectParams d)
  197. {
  198. XmlElement detectParamsN = doc.CreateElement("", "DetectParams", "");
  199. XmlAttribute d_key = doc.CreateAttribute("", "key", "");
  200. d_key.Value = d.Key.ToString();
  201. detectParamsN.Attributes.Append(d_key);
  202. XmlAttribute pos = doc.CreateAttribute("", "pos", "");
  203. pos.Value = d.OffsetPos.ToString();
  204. detectParamsN.Attributes.Append(pos);
  205. XmlAttribute d_linkNum = doc.CreateAttribute("", "linkNum", "");
  206. d_linkNum.Value = d.LinkNum.ToString();
  207. detectParamsN.Attributes.Append(d_linkNum);
  208. XmlAttribute d_group = doc.CreateAttribute("", "group", "");
  209. d_group.Value = d.Group.ToString();
  210. detectParamsN.Attributes.Append(d_group);
  211. XmlAttribute d_name = doc.CreateAttribute("", "name", "");
  212. d_name.Value = d.Name.ToString();
  213. detectParamsN.Attributes.Append(d_name);
  214. XmlAttribute d_owner = doc.CreateAttribute("", "owner", "");
  215. d_owner.Value = d.Owner.ToString();
  216. detectParamsN.Attributes.Append(d_owner);
  217. XmlAttribute d_position = doc.CreateAttribute("", "position", "");
  218. d_position.Value = d.Position.ToString();
  219. detectParamsN.Attributes.Append(d_position);
  220. XmlAttribute d_rotation = doc.CreateAttribute("", "rotation", "");
  221. d_rotation.Value = d.Rotation.ToString();
  222. detectParamsN.Attributes.Append(d_rotation);
  223. XmlAttribute d_type = doc.CreateAttribute("", "type", "");
  224. d_type.Value = d.Type.ToString();
  225. detectParamsN.Attributes.Append(d_type);
  226. XmlAttribute d_velocity = doc.CreateAttribute("", "velocity", "");
  227. d_velocity.Value = d.Velocity.ToString();
  228. detectParamsN.Attributes.Append(d_velocity);
  229. return detectParamsN;
  230. }
  231. /**
  232. * @brief Append elements of an array of objects to an XML parent.
  233. * @param doc = document the parent is part of
  234. * @param parent = parent to append the items to
  235. * @param array = array of objects
  236. * @param tag = <tag ..>...</tag> for each element
  237. */
  238. private static void AppendXMLObjectArray(XmlDocument doc, XmlNode parent, object[] array, string tag)
  239. {
  240. foreach(object o in array)
  241. {
  242. XmlElement element = GetXMLObject(doc, o, tag);
  243. parent.AppendChild(element);
  244. }
  245. }
  246. /**
  247. * @brief Get and XML representation of an object.
  248. * @param doc = document the tag will be put in
  249. * @param o = object to be represented
  250. * @param tag = <tag ...>...</tag>
  251. */
  252. private static XmlElement GetXMLObject(XmlDocument doc, object o, string tag)
  253. {
  254. XmlAttribute typ = doc.CreateAttribute("", "type", "");
  255. XmlElement n = doc.CreateElement("", tag, "");
  256. if(o is LSL_List)
  257. {
  258. typ.Value = "list";
  259. n.Attributes.Append(typ);
  260. AppendXMLObjectArray(doc, n, ((LSL_List)o).Data, "item");
  261. }
  262. else
  263. {
  264. typ.Value = o.GetType().ToString();
  265. n.Attributes.Append(typ);
  266. n.AppendChild(doc.CreateTextNode(o.ToString()));
  267. }
  268. return n;
  269. }
  270. }
  271. }