XMRInstCapture.cs 14 KB

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