XMRInstCapture.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  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. Byte[] snapshotBytes;
  83. using (MemoryStream snapshotStream = new MemoryStream())
  84. {
  85. MigrateOutEventHandler(snapshotStream);
  86. snapshotBytes = snapshotStream.ToArray();
  87. }
  88. string snapshotString = Convert.ToBase64String(snapshotBytes);
  89. XmlElement snapshotN = doc.CreateElement("", "Snapshot", "");
  90. snapshotN.AppendChild(doc.CreateTextNode(snapshotString));
  91. scriptStateN.AppendChild(snapshotN);
  92. m_RunOnePhase = "GetExecutionState B";
  93. CheckRunLockInvariants(true);
  94. // "Running" says whether or not we are accepting new events.
  95. XmlElement runningN = doc.CreateElement("", "Running", "");
  96. runningN.AppendChild(doc.CreateTextNode(m_Running.ToString()));
  97. scriptStateN.AppendChild(runningN);
  98. m_RunOnePhase = "GetExecutionState C";
  99. CheckRunLockInvariants(true);
  100. // "DoGblInit" says whether or not default:state_entry() will init global vars.
  101. XmlElement doGblInitN = doc.CreateElement("", "DoGblInit", "");
  102. doGblInitN.AppendChild(doc.CreateTextNode(doGblInit.ToString()));
  103. scriptStateN.AppendChild(doGblInitN);
  104. m_RunOnePhase = "GetExecutionState D";
  105. CheckRunLockInvariants(true);
  106. // More misc data.
  107. XmlNode permissionsN = doc.CreateElement("", "Permissions", "");
  108. scriptStateN.AppendChild(permissionsN);
  109. XmlAttribute granterA = doc.CreateAttribute("", "granter", "");
  110. granterA.Value = m_Item.PermsGranter.ToString();
  111. permissionsN.Attributes.Append(granterA);
  112. XmlAttribute maskA = doc.CreateAttribute("", "mask", "");
  113. maskA.Value = m_Item.PermsMask.ToString();
  114. permissionsN.Attributes.Append(maskA);
  115. m_RunOnePhase = "GetExecutionState E";
  116. CheckRunLockInvariants(true);
  117. // "DetectParams" are returned by llDetected...() script functions
  118. // for the currently active event, if any.
  119. if(m_DetectParams != null)
  120. {
  121. XmlElement detParArrayN = doc.CreateElement("", "DetectArray", "");
  122. AppendXMLDetectArray(doc, detParArrayN, m_DetectParams);
  123. scriptStateN.AppendChild(detParArrayN);
  124. }
  125. m_RunOnePhase = "GetExecutionState F";
  126. CheckRunLockInvariants(true);
  127. // Save any events we have in the queue.
  128. // <EventQueue>
  129. // <Event Name="...">
  130. // <param>...</param> ...
  131. // <DetectParams>...</DetectParams> ...
  132. // </Event>
  133. // ...
  134. // </EventQueue>
  135. XmlElement queuedEventsN = doc.CreateElement("", "EventQueue", "");
  136. lock(m_QueueLock)
  137. {
  138. foreach(EventParams evt in m_EventQueue)
  139. {
  140. XmlElement singleEventN = doc.CreateElement("", "Event", "");
  141. singleEventN.SetAttribute("Name", evt.EventName);
  142. AppendXMLObjectArray(doc, singleEventN, evt.Params, "param");
  143. AppendXMLDetectArray(doc, singleEventN, evt.DetectParams);
  144. queuedEventsN.AppendChild(singleEventN);
  145. }
  146. }
  147. scriptStateN.AppendChild(queuedEventsN);
  148. m_RunOnePhase = "GetExecutionState G";
  149. CheckRunLockInvariants(true);
  150. // "Plugins" indicate enabled timers and listens, etc.
  151. Object[] pluginData =
  152. AsyncCommandManager.GetSerializationData(m_Engine, m_ItemID);
  153. XmlNode plugins = doc.CreateElement("", "Plugins", "");
  154. AppendXMLObjectArray(doc, plugins, pluginData, "plugin");
  155. scriptStateN.AppendChild(plugins);
  156. m_RunOnePhase = "GetExecutionState H";
  157. CheckRunLockInvariants(true);
  158. // Let script run again.
  159. suspendOnCheckRunHold = false;
  160. m_RunOnePhase = "GetExecutionState leave";
  161. CheckRunLockInvariants(true);
  162. }
  163. // scriptStateN represents the contents of the .state file so
  164. // write the .state file while we are here.
  165. using(FileStream fs = File.Create(m_StateFileName))
  166. {
  167. using(StreamWriter sw = new StreamWriter(fs))
  168. sw.Write(scriptStateN.OuterXml);
  169. }
  170. return scriptStateN;
  171. }
  172. /**
  173. * @brief Write script state to output stream.
  174. * Input:
  175. * stream = stream to write event handler state information to
  176. */
  177. private void MigrateOutEventHandler(Stream stream)
  178. {
  179. // Write script state out, frames and all, to the stream.
  180. // Does not change script state.
  181. stream.WriteByte(migrationVersion);
  182. stream.WriteByte((byte)16);
  183. this.MigrateOut(new BinaryWriter(stream));
  184. }
  185. /**
  186. * @brief Convert an DetectParams[] to corresponding XML.
  187. * DetectParams[] holds the values retrievable by llDetected...() for
  188. * a given event.
  189. */
  190. private static void AppendXMLDetectArray(XmlDocument doc, XmlElement parent, DetectParams[] detect)
  191. {
  192. foreach(DetectParams d in detect)
  193. {
  194. XmlElement detectParamsN = GetXMLDetect(doc, d);
  195. parent.AppendChild(detectParamsN);
  196. }
  197. }
  198. private static XmlElement GetXMLDetect(XmlDocument doc, DetectParams d)
  199. {
  200. XmlElement detectParamsN = doc.CreateElement("", "DetectParams", "");
  201. XmlAttribute d_key = doc.CreateAttribute("", "key", "");
  202. d_key.Value = d.Key.ToString();
  203. detectParamsN.Attributes.Append(d_key);
  204. XmlAttribute pos = doc.CreateAttribute("", "pos", "");
  205. pos.Value = d.OffsetPos.ToString();
  206. detectParamsN.Attributes.Append(pos);
  207. XmlAttribute d_linkNum = doc.CreateAttribute("", "linkNum", "");
  208. d_linkNum.Value = d.LinkNum.ToString();
  209. detectParamsN.Attributes.Append(d_linkNum);
  210. XmlAttribute d_group = doc.CreateAttribute("", "group", "");
  211. d_group.Value = d.Group.ToString();
  212. detectParamsN.Attributes.Append(d_group);
  213. XmlAttribute d_name = doc.CreateAttribute("", "name", "");
  214. d_name.Value = d.Name.ToString();
  215. detectParamsN.Attributes.Append(d_name);
  216. XmlAttribute d_owner = doc.CreateAttribute("", "owner", "");
  217. d_owner.Value = d.Owner.ToString();
  218. detectParamsN.Attributes.Append(d_owner);
  219. XmlAttribute d_position = doc.CreateAttribute("", "position", "");
  220. d_position.Value = d.Position.ToString();
  221. detectParamsN.Attributes.Append(d_position);
  222. XmlAttribute d_rotation = doc.CreateAttribute("", "rotation", "");
  223. d_rotation.Value = d.Rotation.ToString();
  224. detectParamsN.Attributes.Append(d_rotation);
  225. XmlAttribute d_type = doc.CreateAttribute("", "type", "");
  226. d_type.Value = d.Type.ToString();
  227. detectParamsN.Attributes.Append(d_type);
  228. XmlAttribute d_velocity = doc.CreateAttribute("", "velocity", "");
  229. d_velocity.Value = d.Velocity.ToString();
  230. detectParamsN.Attributes.Append(d_velocity);
  231. return detectParamsN;
  232. }
  233. /**
  234. * @brief Append elements of an array of objects to an XML parent.
  235. * @param doc = document the parent is part of
  236. * @param parent = parent to append the items to
  237. * @param array = array of objects
  238. * @param tag = <tag ..>...</tag> for each element
  239. */
  240. private static void AppendXMLObjectArray(XmlDocument doc, XmlNode parent, object[] array, string tag)
  241. {
  242. foreach(object o in array)
  243. {
  244. XmlElement element = GetXMLObject(doc, o, tag);
  245. parent.AppendChild(element);
  246. }
  247. }
  248. /**
  249. * @brief Get and XML representation of an object.
  250. * @param doc = document the tag will be put in
  251. * @param o = object to be represented
  252. * @param tag = <tag ...>...</tag>
  253. */
  254. private static XmlElement GetXMLObject(XmlDocument doc, object o, string tag)
  255. {
  256. XmlAttribute typ = doc.CreateAttribute("", "type", "");
  257. XmlElement n = doc.CreateElement("", tag, "");
  258. if(o is LSL_List)
  259. {
  260. typ.Value = "list";
  261. n.Attributes.Append(typ);
  262. AppendXMLObjectArray(doc, n, ((LSL_List)o).Data, "item");
  263. }
  264. else
  265. {
  266. typ.Value = o.GetType().ToString();
  267. n.Attributes.Append(typ);
  268. n.AppendChild(doc.CreateTextNode(o.ToString()));
  269. }
  270. return n;
  271. }
  272. }
  273. }