XMRInstCapture.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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.Framework;
  31. using OpenSim.Region.ScriptEngine.Shared;
  32. using OpenSim.Region.ScriptEngine.Shared.Api;
  33. using log4net;
  34. using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
  35. using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
  36. using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  37. using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
  38. using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
  39. using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  40. using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
  41. namespace OpenSim.Region.ScriptEngine.Yengine
  42. {
  43. public partial class XMRInstance
  44. {
  45. /********************************************************************************\
  46. * The only method of interest to outside this module is GetExecutionState() *
  47. * which captures the current state of the script into an XML document. *
  48. * *
  49. * The rest of this module contains support routines for GetExecutionState(). *
  50. \********************************************************************************/
  51. /**
  52. * @brief Create an XML element that gives the current state of the script.
  53. * <ScriptState Engine="YEngine" SourceHash=m_ObjCode.sourceHash Asset=m_Item.AssetID>
  54. * <Snapshot>globalsandstackdump</Snapshot>
  55. * <Running>m_Running</Running>
  56. * <DetectArray ...
  57. * <EventQueue ...
  58. * <Permissions ...
  59. * <Plugins />
  60. * </ScriptState>
  61. * Updates the .state file while we're at it.
  62. */
  63. public XmlElement GetExecutionState(XmlDocument doc)
  64. {
  65. // When we're detaching an attachment, we need to wait here.
  66. // Change this to a 5 second timeout. If things do mess up,
  67. // we don't want to be stuck forever.
  68. //
  69. m_DetachReady.WaitOne(5000, false);
  70. XmlElement scriptStateN = doc.CreateElement("", "ScriptState", "");
  71. scriptStateN.SetAttribute("Engine", m_Engine.ScriptEngineName);
  72. scriptStateN.SetAttribute("Asset", m_Item.AssetID.ToString());
  73. scriptStateN.SetAttribute("SourceHash", m_ObjCode.sourceHash);
  74. // Make sure we aren't executing part of the script so it stays
  75. // stable. Setting suspendOnCheckRun tells CheckRun() to suspend
  76. // and return out so RunOne() will release the lock asap.
  77. suspendOnCheckRunHold = true;
  78. lock(m_RunLock)
  79. {
  80. //m_RunOnePhase = "GetExecutionState enter";
  81. //CheckRunLockInvariants(true);
  82. // Get copy of script globals and stack in relocateable form.
  83. Byte[] snapshotBytes;
  84. using (MemoryStream snapshotStream = new MemoryStream())
  85. {
  86. MigrateOutEventHandler(snapshotStream);
  87. snapshotBytes = snapshotStream.ToArray();
  88. }
  89. string snapshotString = Convert.ToBase64String(snapshotBytes);
  90. XmlElement snapshotN = doc.CreateElement("", "Snapshot", "");
  91. snapshotN.AppendChild(doc.CreateTextNode(snapshotString));
  92. scriptStateN.AppendChild(snapshotN);
  93. //m_RunOnePhase = "GetExecutionState B";
  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. // "DoGblInit" says whether or not default:state_entry() will init global vars.
  100. XmlElement doGblInitN = doc.CreateElement("", "DoGblInit", "");
  101. doGblInitN.AppendChild(doc.CreateTextNode(doGblInit.ToString()));
  102. scriptStateN.AppendChild(doGblInitN);
  103. //m_RunOnePhase = "GetExecutionState D";
  104. if(m_XMRLSLApi is not null)
  105. {
  106. double scriptTime = Util.GetTimeStampMS() - m_XMRLSLApi.getLSLTimer();
  107. XmlElement scriptTimeN = doc.CreateElement("", "scrpTime", "");
  108. scriptTimeN.AppendChild(doc.CreateTextNode(scriptTime.ToString()));
  109. scriptStateN.AppendChild(scriptTimeN);
  110. }
  111. if (m_minEventDelay != 0.0)
  112. {
  113. XmlElement minEventDelayN = doc.CreateElement("", "mEvtDly", "");
  114. minEventDelayN.AppendChild(doc.CreateTextNode(m_minEventDelay.ToString()));
  115. scriptStateN.AppendChild(minEventDelayN);
  116. //m_RunOnePhase = "GetExecutionState D";
  117. }
  118. // More misc data.
  119. XmlNode permissionsN = doc.CreateElement("", "Permissions", "");
  120. scriptStateN.AppendChild(permissionsN);
  121. XmlAttribute granterA = doc.CreateAttribute("", "granter", "");
  122. granterA.Value = m_Item.PermsGranter.ToString();
  123. permissionsN.Attributes.Append(granterA);
  124. XmlAttribute maskA = doc.CreateAttribute("", "mask", "");
  125. maskA.Value = m_Item.PermsMask.ToString();
  126. permissionsN.Attributes.Append(maskA);
  127. //m_RunOnePhase = "GetExecutionState E";
  128. // "DetectParams" are returned by llDetected...() script functions
  129. // for the currently active event, if any.
  130. var detectParams = m_DetectParams;
  131. if (detectParams is not null)
  132. {
  133. XmlElement detParArrayN = doc.CreateElement("", "DetectArray", "");
  134. AppendXMLDetectArray(doc, detParArrayN, detectParams);
  135. scriptStateN.AppendChild(detParArrayN);
  136. }
  137. //m_RunOnePhase = "GetExecutionState F";
  138. // Save any events we have in the queue.
  139. // <EventQueue>
  140. // <Event Name="...">
  141. // <param>...</param> ...
  142. // <DetectParams>...</DetectParams> ...
  143. // </Event>
  144. // ...
  145. // </EventQueue>
  146. XmlElement queuedEventsN = doc.CreateElement("", "EventQueue", "");
  147. lock(m_QueueLock)
  148. {
  149. foreach(EventParams evt in m_EventQueue)
  150. {
  151. XmlElement singleEventN = doc.CreateElement("", "Event", "");
  152. singleEventN.SetAttribute("Name", evt.EventName);
  153. AppendXMLObjectArray(doc, singleEventN, evt.Params, "param");
  154. AppendXMLDetectArray(doc, singleEventN, evt.DetectParams);
  155. queuedEventsN.AppendChild(singleEventN);
  156. }
  157. }
  158. scriptStateN.AppendChild(queuedEventsN);
  159. //m_RunOnePhase = "GetExecutionState G";
  160. // "Plugins" indicate enabled timers and listens, etc.
  161. Object[] pluginData = AsyncCommandManager.GetSerializationData(m_Engine, m_ItemID);
  162. XmlNode plugins = doc.CreateElement("", "Plugins", "");
  163. AppendXMLObjectArray(doc, plugins, pluginData, "plugin");
  164. scriptStateN.AppendChild(plugins);
  165. //m_RunOnePhase = "GetExecutionState H";
  166. // Let script run again.
  167. suspendOnCheckRunHold = false;
  168. //m_RunOnePhase = "GetExecutionState leave";
  169. }
  170. // scriptStateN represents the contents of the .state file so
  171. // write the .state file while we are here.
  172. using(FileStream fs = File.Create(m_StateFileName))
  173. {
  174. using(StreamWriter sw = new StreamWriter(fs))
  175. sw.Write(scriptStateN.OuterXml);
  176. }
  177. return scriptStateN;
  178. }
  179. /**
  180. * @brief Write script state to output stream.
  181. * Input:
  182. * stream = stream to write event handler state information to
  183. */
  184. private void MigrateOutEventHandler(Stream stream)
  185. {
  186. // Write script state out, frames and all, to the stream.
  187. // Does not change script state.
  188. stream.WriteByte(migrationVersion);
  189. stream.WriteByte((byte)16);
  190. MigrateOut(new BinaryWriter(stream));
  191. }
  192. /**
  193. * @brief Convert an DetectParams[] to corresponding XML.
  194. * DetectParams[] holds the values retrievable by llDetected...() for
  195. * a given event.
  196. */
  197. private static void AppendXMLDetectArray(XmlDocument doc, XmlElement parent, DetectParams[] detect)
  198. {
  199. try
  200. {
  201. foreach(DetectParams d in detect)
  202. {
  203. XmlElement detectParamsN = GetXMLDetect(doc, d);
  204. parent.AppendChild(detectParamsN);
  205. }
  206. }
  207. catch { }
  208. }
  209. private static XmlElement GetXMLDetect(XmlDocument doc, DetectParams d)
  210. {
  211. XmlElement detectParamsN = doc.CreateElement("", "DetectParams", "");
  212. XmlAttribute d_key = doc.CreateAttribute("", "key", "");
  213. d_key.Value = d.Key.ToString();
  214. detectParamsN.Attributes.Append(d_key);
  215. XmlAttribute pos = doc.CreateAttribute("", "pos", "");
  216. pos.Value = d.OffsetPos.ToString();
  217. detectParamsN.Attributes.Append(pos);
  218. XmlAttribute d_linkNum = doc.CreateAttribute("", "linkNum", "");
  219. d_linkNum.Value = d.LinkNum.ToString();
  220. detectParamsN.Attributes.Append(d_linkNum);
  221. XmlAttribute d_group = doc.CreateAttribute("", "group", "");
  222. d_group.Value = d.Group.ToString();
  223. detectParamsN.Attributes.Append(d_group);
  224. XmlAttribute d_name = doc.CreateAttribute("", "name", "");
  225. d_name.Value = d.Name.ToString();
  226. detectParamsN.Attributes.Append(d_name);
  227. XmlAttribute d_owner = doc.CreateAttribute("", "owner", "");
  228. d_owner.Value = d.Owner.ToString();
  229. detectParamsN.Attributes.Append(d_owner);
  230. XmlAttribute d_position = doc.CreateAttribute("", "position", "");
  231. d_position.Value = d.Position.ToString();
  232. detectParamsN.Attributes.Append(d_position);
  233. XmlAttribute d_rotation = doc.CreateAttribute("", "rotation", "");
  234. d_rotation.Value = d.Rotation.ToString();
  235. detectParamsN.Attributes.Append(d_rotation);
  236. XmlAttribute d_type = doc.CreateAttribute("", "type", "");
  237. d_type.Value = d.Type.ToString();
  238. detectParamsN.Attributes.Append(d_type);
  239. XmlAttribute d_velocity = doc.CreateAttribute("", "velocity", "");
  240. d_velocity.Value = d.Velocity.ToString();
  241. detectParamsN.Attributes.Append(d_velocity);
  242. return detectParamsN;
  243. }
  244. /**
  245. * @brief Append elements of an array of objects to an XML parent.
  246. * @param doc = document the parent is part of
  247. * @param parent = parent to append the items to
  248. * @param array = array of objects
  249. * @param tag = <tag ..>...</tag> for each element
  250. */
  251. private static void AppendXMLObjectArray(XmlDocument doc, XmlNode parent, object[] array, string tag)
  252. {
  253. foreach(object o in array)
  254. {
  255. XmlElement element = GetXMLObject(doc, o, tag);
  256. parent.AppendChild(element);
  257. }
  258. }
  259. /**
  260. * @brief Get and XML representation of an object.
  261. * @param doc = document the tag will be put in
  262. * @param o = object to be represented
  263. * @param tag = <tag ...>...</tag>
  264. */
  265. private static XmlElement GetXMLObject(XmlDocument doc, object o, string tag)
  266. {
  267. XmlAttribute typ = doc.CreateAttribute("", "type", "");
  268. XmlElement n = doc.CreateElement("", tag, "");
  269. if(o is LSL_List)
  270. {
  271. typ.Value = "list";
  272. n.Attributes.Append(typ);
  273. AppendXMLObjectArray(doc, n, ((LSL_List)o).Data, "item");
  274. }
  275. else
  276. {
  277. typ.Value = o.GetType().ToString();
  278. n.Attributes.Append(typ);
  279. n.AppendChild(doc.CreateTextNode(o.ToString()));
  280. }
  281. return n;
  282. }
  283. }
  284. }