XMRInstCtor.cs 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
  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.Threading;
  29. using System.Reflection;
  30. using System.Collections;
  31. using System.Collections.Generic;
  32. using System.Runtime.Remoting.Lifetime;
  33. using System.Security.Policy;
  34. using System.IO;
  35. using System.Xml;
  36. using System.Text;
  37. using OpenMetaverse;
  38. using OpenSim.Framework;
  39. using OpenSim.Region.ScriptEngine.Interfaces;
  40. using OpenSim.Region.ScriptEngine.Shared;
  41. using OpenSim.Region.ScriptEngine.Shared.Api;
  42. using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
  43. using OpenSim.Region.ScriptEngine.Yengine;
  44. using OpenSim.Region.Framework.Scenes;
  45. using log4net;
  46. using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
  47. using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
  48. using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  49. using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
  50. using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
  51. using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  52. using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
  53. namespace OpenSim.Region.ScriptEngine.Yengine
  54. {
  55. public partial class XMRInstance
  56. {
  57. /****************************************************************************\
  58. * The only method of interest to outside this module is the Initializer. *
  59. * *
  60. * The rest of this module contains support routines for the Initializer. *
  61. \****************************************************************************/
  62. /**
  63. * @brief Initializer, loads script in memory and all ready for running.
  64. * @param engine = YEngine instance this is part of
  65. * @param scriptBasePath = directory name where files are
  66. * @param stackSize = number of bytes to allocate for stacks
  67. * @param errors = return compiler errors in this array
  68. * @param forceRecomp = force recompile
  69. * Throws exception if any error, so it was successful if it returns.
  70. */
  71. public void Initialize(Yengine engine, string scriptBasePath,
  72. int stackSize, int heapSize, ArrayList errors)
  73. {
  74. if(stackSize < 16384)
  75. stackSize = 16384;
  76. if(heapSize < 16384)
  77. heapSize = 16384;
  78. // Save all call parameters in instance vars for easy access.
  79. m_Engine = engine;
  80. m_ScriptBasePath = scriptBasePath;
  81. m_StackSize = stackSize;
  82. m_StackLeft = stackSize;
  83. m_HeapSize = heapSize;
  84. m_localsHeapUsed = 0;
  85. m_arraysHeapUsed = 0;
  86. m_CompilerErrors = errors;
  87. m_StateFileName = GetStateFileName(scriptBasePath, m_ItemID);
  88. // Not in any XMRInstQueue.
  89. m_NextInst = this;
  90. m_PrevInst = this;
  91. // Set up list of API calls it has available.
  92. // This also gets the API modules ready to accept setup data, such as
  93. // active listeners being restored.
  94. IScriptApi scriptApi;
  95. ApiManager am = new ApiManager();
  96. foreach(string api in am.GetApis())
  97. {
  98. // Instantiate the API for this script instance.
  99. if(api != "LSL")
  100. scriptApi = am.CreateApi(api);
  101. else
  102. scriptApi = m_XMRLSLApi = new XMRLSL_Api();
  103. // Connect it up to the instance.
  104. InitScriptApi(engine, api, scriptApi);
  105. }
  106. m_XMRLSLApi.InitXMRLSLApi(this);
  107. // Get object loaded, compiling script and reading .state file as
  108. // necessary to restore the state.
  109. suspendOnCheckRunHold = true;
  110. InstantiateScript();
  111. m_SourceCode = null;
  112. if(m_ObjCode == null)
  113. throw new ArgumentNullException("m_ObjCode");
  114. if(m_ObjCode.scriptEventHandlerTable == null)
  115. throw new ArgumentNullException("m_ObjCode.scriptEventHandlerTable");
  116. suspendOnCheckRunHold = false;
  117. suspendOnCheckRunTemp = false;
  118. }
  119. private void InitScriptApi(Yengine engine, string api, IScriptApi scriptApi)
  120. {
  121. // Set up m_ApiManager_<APINAME> = instance pointer.
  122. engine.m_XMRInstanceApiCtxFieldInfos[api].SetValue(this, scriptApi);
  123. // Initialize the API instance.
  124. scriptApi.Initialize(m_Engine, m_Part, m_Item);
  125. this.InitApi(api, scriptApi);
  126. }
  127. /*
  128. * Get script object code loaded in memory and all ready to run,
  129. * ready to resume it from where the .state file says it was last
  130. */
  131. private void InstantiateScript()
  132. {
  133. bool compiledIt = false;
  134. ScriptObjCode objCode;
  135. // If source code string is empty, use the asset ID as the object file name.
  136. // Allow lines of // comments at the beginning (for such as engine selection).
  137. int i, j, len;
  138. if(m_SourceCode == null)
  139. m_SourceCode = String.Empty;
  140. for(len = m_SourceCode.Length; len > 0; --len)
  141. {
  142. if(m_SourceCode[len - 1] > ' ')
  143. break;
  144. }
  145. for(i = 0; i < len; i++)
  146. {
  147. char c = m_SourceCode[i];
  148. if(c <= ' ')
  149. continue;
  150. if(c != '/')
  151. break;
  152. if((i + 1 >= len) || (m_SourceCode[i + 1] != '/'))
  153. break;
  154. i = m_SourceCode.IndexOf('\n', i);
  155. if(i < 0)
  156. i = len - 1;
  157. }
  158. if((i >= len))
  159. {
  160. // Source consists of nothing but // comments and whitespace,
  161. // or we are being forced to use the asset-id as the key, to
  162. // open an already existing object code file.
  163. m_ScriptObjCodeKey = m_Item.AssetID.ToString();
  164. if(i >= len)
  165. m_SourceCode = "";
  166. }
  167. else
  168. {
  169. // Make up dictionary key for the object code.
  170. // Use the same object code for identical source code
  171. // regardless of asset ID, so we don't care if they
  172. // copy scripts or not.
  173. byte[] scbytes = System.Text.Encoding.UTF8.GetBytes(m_SourceCode);
  174. StringBuilder sb = new StringBuilder((256 + 5) / 6);
  175. using (System.Security.Cryptography.SHA256 sha = System.Security.Cryptography.SHA256.Create())
  176. ByteArrayToSixbitStr(sb, sha.ComputeHash(scbytes));
  177. m_ScriptObjCodeKey = sb.ToString();
  178. // But source code can be just a sixbit string itself
  179. // that identifies an already existing object code file.
  180. if(len - i == m_ScriptObjCodeKey.Length)
  181. {
  182. for(j = len; --j >= i;)
  183. {
  184. if(sixbit.IndexOf(m_SourceCode[j]) < 0)
  185. break;
  186. }
  187. if(j < i)
  188. {
  189. m_ScriptObjCodeKey = m_SourceCode.Substring(i, len - i);
  190. m_SourceCode = "";
  191. }
  192. }
  193. }
  194. // There may already be an ScriptObjCode struct in memory that
  195. // we can use. If not, try to compile it.
  196. lock(m_CompileLock)
  197. {
  198. if(!m_CompiledScriptObjCode.TryGetValue(m_ScriptObjCodeKey, out objCode) || m_ForceRecomp)
  199. {
  200. objCode = TryToCompile();
  201. compiledIt = true;
  202. }
  203. // Loaded successfully, increment reference count.
  204. // If we just compiled it though, reset count to 0 first as
  205. // this is the one-and-only existance of this objCode struct,
  206. // and we want any old ones for this source code to be garbage
  207. // collected.
  208. if(compiledIt)
  209. {
  210. m_CompiledScriptObjCode[m_ScriptObjCodeKey] = objCode;
  211. objCode.refCount = 0;
  212. }
  213. objCode.refCount++;
  214. // Now set up to decrement ref count on dispose.
  215. m_ObjCode = objCode;
  216. }
  217. try
  218. {
  219. // Fill in script instance from object code
  220. // Script instance is put in a "never-ever-has-run-before" state.
  221. LoadObjCode();
  222. // Fill in script intial state
  223. // - either as loaded from a .state file
  224. // - or initial default state_entry() event
  225. LoadInitialState();
  226. }
  227. catch
  228. {
  229. // If any error loading, decrement object code reference count.
  230. DecObjCodeRefCount();
  231. throw;
  232. }
  233. }
  234. private const string sixbit = "0123456789_abcdefghijklmnopqrstuvwxyz@ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  235. private static void ByteArrayToSixbitStr(StringBuilder sb, byte[] bytes)
  236. {
  237. int bit = 0;
  238. int val = 0;
  239. foreach(byte b in bytes)
  240. {
  241. val |= (int)((uint)b << bit);
  242. bit += 8;
  243. while(bit >= 6)
  244. {
  245. sb.Append(sixbit[val & 63]);
  246. val >>= 6;
  247. bit -= 6;
  248. }
  249. }
  250. if(bit > 0)
  251. sb.Append(sixbit[val & 63]);
  252. }
  253. // Try to create object code from source code
  254. // If error, just throw exception
  255. private ScriptObjCode TryToCompile()
  256. {
  257. m_CompilerErrors.Clear();
  258. // If object file exists, create ScriptObjCode directly from that.
  259. // Otherwise, compile the source to create object file then create
  260. // ScriptObjCode from that.
  261. string assetID = m_Item.AssetID.ToString();
  262. m_CameFrom = "asset://" + assetID;
  263. ScriptObjCode objCode = Compile();
  264. if(m_CompilerErrors.Count != 0)
  265. throw new Exception("compilation errors");
  266. if(objCode == null)
  267. throw new Exception("compilation failed");
  268. return objCode;
  269. }
  270. /*
  271. * Retrieve source from asset server.
  272. */
  273. private string FetchSource(string cameFrom)
  274. {
  275. m_log.Debug("[YEngine]: fetching source " + cameFrom);
  276. if(!cameFrom.StartsWith("asset://"))
  277. throw new Exception("unable to retrieve source from " + cameFrom);
  278. string assetID = cameFrom.Substring(8);
  279. AssetBase asset = m_Engine.World.AssetService.Get(assetID);
  280. if(asset == null)
  281. throw new Exception("source not found " + cameFrom);
  282. string source = Encoding.UTF8.GetString(asset.Data);
  283. if(EmptySource(source))
  284. throw new Exception("fetched source empty " + cameFrom);
  285. return source;
  286. }
  287. /*
  288. * Fill in script object initial contents.
  289. * Set the initial state to "default".
  290. */
  291. private void LoadObjCode()
  292. {
  293. // Script must leave this much stack remaining on calls to CheckRun().
  294. this.stackLimit = m_StackSize / 2;
  295. // This is how many total heap bytes script is allowed to use.
  296. this.heapLimit = m_HeapSize;
  297. // Allocate global variable arrays.
  298. this.glblVars.AllocVarArrays(m_ObjCode.glblSizes);
  299. // Script can handle these event codes.
  300. m_HaveEventHandlers = new bool[m_ObjCode.scriptEventHandlerTable.GetLength(1)];
  301. for(int i = m_ObjCode.scriptEventHandlerTable.GetLength(0); --i >= 0;)
  302. {
  303. for(int j = m_ObjCode.scriptEventHandlerTable.GetLength(1); --j >= 0;)
  304. {
  305. if(m_ObjCode.scriptEventHandlerTable[i, j] != null)
  306. {
  307. m_HaveEventHandlers[j] = true;
  308. }
  309. }
  310. }
  311. }
  312. /*
  313. * LoadInitialState()
  314. * if no state XML file exists for the asset,
  315. * post initial default state events
  316. * else
  317. * try to restore from .state file
  318. * If any error, throw exception
  319. */
  320. private void LoadInitialState()
  321. {
  322. // If no .state file exists, start from default state
  323. // Otherwise, read initial state from the .state file
  324. if(!File.Exists(m_StateFileName))
  325. {
  326. m_Running = true; // event processing is enabled
  327. eventCode = ScriptEventCode.None; // not processing any event
  328. // default state_entry() must initialize global variables
  329. doGblInit = true;
  330. stateCode = 0;
  331. PostEvent(new EventParams("state_entry",
  332. zeroObjectArray,
  333. zeroDetectParams));
  334. }
  335. else
  336. {
  337. try
  338. {
  339. string xml;
  340. using (FileStream fs = File.Open(m_StateFileName,
  341. FileMode.Open,
  342. FileAccess.Read))
  343. {
  344. using(StreamReader ss = new StreamReader(fs))
  345. xml = ss.ReadToEnd();
  346. }
  347. XmlDocument doc = new XmlDocument();
  348. doc.LoadXml(xml);
  349. LoadScriptState(doc);
  350. }
  351. catch
  352. {
  353. File.Delete(m_StateFileName);
  354. m_Running = true; // event processing is enabled
  355. eventCode = ScriptEventCode.None; // not processing any event
  356. // default state_entry() must initialize global variables
  357. glblVars.AllocVarArrays(m_ObjCode.glblSizes); // reset globals
  358. doGblInit = true;
  359. stateCode = 0;
  360. PostEvent(new EventParams("state_entry",
  361. zeroObjectArray,
  362. zeroDetectParams));
  363. }
  364. }
  365. // Post event(s) saying what caused the script to start.
  366. if(m_PostOnRez)
  367. {
  368. PostEvent(new EventParams("on_rez",
  369. new Object[] { m_StartParam },
  370. zeroDetectParams));
  371. }
  372. switch(m_StateSource)
  373. {
  374. case StateSource.AttachedRez:
  375. PostEvent(new EventParams("attach",
  376. new object[] { m_Part.ParentGroup.AttachedAvatar.ToString() },
  377. zeroDetectParams));
  378. break;
  379. case StateSource.PrimCrossing:
  380. PostEvent(new EventParams("changed",
  381. sbcCR,
  382. zeroDetectParams));
  383. break;
  384. case StateSource.Teleporting:
  385. PostEvent(new EventParams("changed",
  386. sbcCR,
  387. zeroDetectParams));
  388. PostEvent(new EventParams("changed",
  389. sbcCT,
  390. zeroDetectParams));
  391. break;
  392. case StateSource.RegionStart:
  393. PostEvent(new EventParams("changed",
  394. sbcCRS,
  395. zeroDetectParams));
  396. break;
  397. }
  398. }
  399. private static Object[] sbcCRS = new Object[] { ScriptBaseClass.CHANGED_REGION_START };
  400. private static Object[] sbcCR = new Object[] { ScriptBaseClass.CHANGED_REGION };
  401. private static Object[] sbcCT = new Object[] { ScriptBaseClass.CHANGED_TELEPORT };
  402. /**
  403. * @brief Save compilation error messages for later retrieval
  404. * via GetScriptErrors().
  405. */
  406. private void ErrorHandler(Token token, string message)
  407. {
  408. if(token != null)
  409. {
  410. string srcloc = token.SrcLoc;
  411. if(srcloc.StartsWith(m_CameFrom))
  412. srcloc = srcloc.Substring(m_CameFrom.Length);
  413. m_CompilerErrors.Add(srcloc + " Error: " + message);
  414. }
  415. else if(message != null)
  416. m_CompilerErrors.Add("(0,0) Error: " + message);
  417. else
  418. m_CompilerErrors.Add("(0,0) Error compiling, see exception in log");
  419. }
  420. /**
  421. * @brief Load script state from the given XML doc into the script memory
  422. * <ScriptState Engine="YEngine" Asset=...>
  423. * <Running>...</Running>
  424. * <DoGblInit>...</DoGblInit>
  425. * <Permissions granted=... mask=... />
  426. * RestoreDetectParams()
  427. * <Plugins>
  428. * ExtractXMLObjectArray("plugin")
  429. * </Plugins>
  430. * <Snapshot>
  431. * MigrateInEventHandler()
  432. * </Snapshot>
  433. * </ScriptState>
  434. */
  435. private void LoadScriptState(XmlDocument doc)
  436. {
  437. // Everything we know is enclosed in <ScriptState>...</ScriptState>
  438. XmlElement scriptStateN = (XmlElement)doc.SelectSingleNode("ScriptState");
  439. if(scriptStateN == null)
  440. throw new Exception("no <ScriptState> tag");
  441. XmlElement XvariablesN = null;
  442. string sen = scriptStateN.GetAttribute("Engine");
  443. if((sen == null) || (sen != m_Engine.ScriptEngineName))
  444. {
  445. XvariablesN = (XmlElement)scriptStateN.SelectSingleNode("Variables");
  446. if(XvariablesN == null)
  447. throw new Exception("<ScriptState> missing Engine=\"YEngine\" attribute");
  448. processXstate(doc);
  449. return;
  450. }
  451. // AssetID is unique for the script source text so make sure the
  452. // state file was written for that source file
  453. string assetID = scriptStateN.GetAttribute("Asset");
  454. if(assetID != m_Item.AssetID.ToString())
  455. throw new Exception("<ScriptState> assetID mismatch");
  456. // Also match the sourceHash in case script was
  457. // loaded via 'xmroption fetchsource' and has changed
  458. string sourceHash = scriptStateN.GetAttribute("SourceHash");
  459. if((sourceHash == null) || (sourceHash != m_ObjCode.sourceHash))
  460. throw new Exception("<ScriptState> SourceHash mismatch");
  461. // Get various attributes
  462. XmlElement runningN = (XmlElement)scriptStateN.SelectSingleNode("Running");
  463. m_Running = bool.Parse(runningN.InnerText);
  464. XmlElement doGblInitN = (XmlElement)scriptStateN.SelectSingleNode("DoGblInit");
  465. doGblInit = bool.Parse(doGblInitN.InnerText);
  466. if (m_XMRLSLApi != null)
  467. {
  468. XmlElement scpttimeN = (XmlElement)scriptStateN.SelectSingleNode("scrpTime");
  469. if (scpttimeN != null && Double.TryParse(scpttimeN.InnerText, out double t))
  470. {
  471. m_XMRLSLApi.SetLSLTimer(Util.GetTimeStampMS() - t);
  472. }
  473. }
  474. double minEventDelay = 0.0;
  475. XmlElement minEventDelayN = (XmlElement)scriptStateN.SelectSingleNode("mEvtDly");
  476. if (minEventDelayN != null)
  477. minEventDelay = Double.Parse(minEventDelayN.InnerText);
  478. // get values used by stuff like llDetectedGrab, etc.
  479. DetectParams[] detParams = RestoreDetectParams(scriptStateN.SelectSingleNode("DetectArray"));
  480. // Restore queued events
  481. LinkedList<EventParams> eventQueue = RestoreEventQueue(scriptStateN.SelectSingleNode("EventQueue"));
  482. // Restore timers and listeners
  483. XmlElement pluginN = (XmlElement)scriptStateN.SelectSingleNode("Plugins");
  484. Object[] pluginData = ExtractXMLObjectArray(pluginN, "plugin");
  485. // Script's global variables and stack contents
  486. XmlElement snapshotN = (XmlElement)scriptStateN.SelectSingleNode("Snapshot");
  487. Byte[] data = Convert.FromBase64String(snapshotN.InnerText);
  488. using(MemoryStream ms = new MemoryStream())
  489. {
  490. ms.Write(data, 0, data.Length);
  491. ms.Seek(0, SeekOrigin.Begin);
  492. MigrateInEventHandler(ms);
  493. }
  494. XmlElement permissionsN = (XmlElement)scriptStateN.SelectSingleNode("Permissions");
  495. m_Item.PermsGranter = new UUID(permissionsN.GetAttribute("granter"));
  496. m_Item.PermsMask = Convert.ToInt32(permissionsN.GetAttribute("mask"));
  497. m_Part.Inventory.UpdateInventoryItem(m_Item, false, false);
  498. // Restore event queues, preserving any events that queued
  499. // whilst we were restoring the state
  500. lock (m_QueueLock)
  501. {
  502. m_DetectParams = detParams;
  503. foreach(EventParams evt in m_EventQueue)
  504. eventQueue.AddLast(evt);
  505. m_EventQueue = eventQueue;
  506. for(int i = m_EventCounts.Length; --i >= 0;)
  507. m_EventCounts[i] = 0;
  508. foreach(EventParams evt in m_EventQueue)
  509. {
  510. if(m_eventCodeMap.TryGetValue(evt.EventName, out ScriptEventCode eventCode))
  511. m_EventCounts[(int)eventCode]++;
  512. }
  513. }
  514. // Requeue timer and listeners (possibly queuing new events)
  515. AsyncCommandManager.CreateFromData(m_Engine,
  516. m_LocalID, m_ItemID, m_Part.UUID,
  517. pluginData);
  518. MinEventDelay = minEventDelay;
  519. }
  520. private void processXstate(XmlDocument doc)
  521. {
  522. XmlNodeList rootL = doc.GetElementsByTagName("ScriptState");
  523. if (rootL.Count != 1)
  524. throw new Exception("Xstate <ScriptState> missing");
  525. XmlNode rootNode = rootL[0];
  526. if (rootNode == null)
  527. throw new Exception("Xstate root missing");
  528. string stateName = "";
  529. bool running = false;
  530. UUID permsGranter = UUID.Zero;
  531. int permsMask = 0;
  532. double minEventDelay = 0.0;
  533. Object[] pluginData = new Object[0];
  534. LinkedList<EventParams> eventQueue = new LinkedList<EventParams>();
  535. Dictionary<string, int> intNames = new Dictionary<string, int>();
  536. Dictionary<string, int> doubleNames = new Dictionary<string, int>();
  537. Dictionary<string, int> stringNames = new Dictionary<string, int>();
  538. Dictionary<string, int> vectorNames = new Dictionary<string, int>();
  539. Dictionary<string, int> rotationNames = new Dictionary<string, int>();
  540. Dictionary<string, int> listNames = new Dictionary<string, int>();
  541. int nn = m_ObjCode.globalVarNames.Count;
  542. int[] ints = null;
  543. double[] doubles = null;
  544. string[] strings = null;
  545. LSL_Vector[] vectors = null;
  546. LSL_Rotation[] rotations = null;
  547. LSL_List[] lists = null;
  548. if (nn > 0)
  549. {
  550. if (m_ObjCode.globalVarNames.ContainsKey("iarIntegers"))
  551. {
  552. getvarNames(m_ObjCode.globalVarNames["iarIntegers"], intNames);
  553. ints = new int[m_ObjCode.globalVarNames["iarIntegers"].Count];
  554. }
  555. if (m_ObjCode.globalVarNames.ContainsKey("iarFloats"))
  556. {
  557. getvarNames(m_ObjCode.globalVarNames["iarFloats"], doubleNames);
  558. doubles = new double[m_ObjCode.globalVarNames["iarFloats"].Count];
  559. }
  560. if (m_ObjCode.globalVarNames.ContainsKey("iarVectors"))
  561. {
  562. getvarNames(m_ObjCode.globalVarNames["iarVectors"], vectorNames);
  563. vectors = new LSL_Vector[m_ObjCode.globalVarNames["iarVectors"].Count];
  564. }
  565. if (m_ObjCode.globalVarNames.ContainsKey("iarRotations"))
  566. {
  567. getvarNames(m_ObjCode.globalVarNames["iarRotations"], rotationNames);
  568. rotations = new LSL_Rotation[m_ObjCode.globalVarNames["iarRotations"].Count];
  569. }
  570. if (m_ObjCode.globalVarNames.ContainsKey("iarStrings"))
  571. {
  572. getvarNames(m_ObjCode.globalVarNames["iarStrings"], stringNames);
  573. strings = new string[m_ObjCode.globalVarNames["iarStrings"].Count];
  574. }
  575. if (m_ObjCode.globalVarNames.ContainsKey("iarLists"))
  576. {
  577. getvarNames(m_ObjCode.globalVarNames["iarLists"], listNames);
  578. lists = new LSL_List[m_ObjCode.globalVarNames["iarLists"].Count];
  579. }
  580. }
  581. int heapsz = 0;
  582. try
  583. {
  584. XmlNodeList partL = rootNode.ChildNodes;
  585. foreach (XmlNode part in partL)
  586. {
  587. switch (part.Name)
  588. {
  589. case "State":
  590. stateName = part.InnerText;
  591. break;
  592. case "Running":
  593. running = bool.Parse(part.InnerText);
  594. break;
  595. case "Variables":
  596. int indx;
  597. XmlNodeList varL = part.ChildNodes;
  598. foreach (XmlNode var in varL)
  599. {
  600. string varName;
  601. object o = ReadXTypedValue(var, out varName);
  602. Type otype = o.GetType();
  603. if (otype == typeof(LSL_Integer))
  604. {
  605. if (intNames.TryGetValue(varName, out indx))
  606. ints[indx] = ((LSL_Integer)o);
  607. continue;
  608. }
  609. if (otype == typeof(LSL_Float))
  610. {
  611. if (doubleNames.TryGetValue(varName, out indx))
  612. doubles[indx] = ((LSL_Float)o);
  613. continue;
  614. }
  615. if (otype == typeof(LSL_String))
  616. {
  617. if (stringNames.TryGetValue(varName, out indx))
  618. {
  619. strings[indx] = ((LSL_String)o);
  620. heapsz += ((LSL_String)o).Length;
  621. }
  622. continue;
  623. }
  624. if (otype == typeof(LSL_Rotation))
  625. {
  626. if (rotationNames.TryGetValue(varName, out indx))
  627. rotations[indx] = ((LSL_Rotation)o);
  628. continue;
  629. }
  630. if (otype == typeof(LSL_Vector))
  631. {
  632. if (vectorNames.TryGetValue(varName, out indx))
  633. vectors[indx] = ((LSL_Vector)o);
  634. continue;
  635. }
  636. if (otype == typeof(LSL_Key))
  637. {
  638. if (stringNames.TryGetValue(varName, out indx))
  639. {
  640. strings[indx] = ((LSL_Key)o);
  641. heapsz += ((LSL_String)o).Length;
  642. }
  643. continue;
  644. }
  645. if (otype == typeof(UUID))
  646. {
  647. if (stringNames.TryGetValue(varName, out indx))
  648. {
  649. LSL_String id = ((UUID)o).ToString();
  650. strings[indx] = (id);
  651. heapsz += id.Length;
  652. }
  653. continue;
  654. }
  655. if (otype == typeof(LSL_List))
  656. {
  657. if (listNames.TryGetValue(varName, out indx))
  658. {
  659. LSL_List lo = (LSL_List)o;
  660. lists[indx] = (lo);
  661. heapsz += lo.Size;
  662. }
  663. continue;
  664. }
  665. }
  666. break;
  667. case "Queue":
  668. XmlNodeList itemL = part.ChildNodes;
  669. foreach (XmlNode item in itemL)
  670. {
  671. List<Object> parms = new List<Object>();
  672. List<DetectParams> detected = new List<DetectParams>();
  673. string eventName = item.Attributes.GetNamedItem("event").Value;
  674. XmlNodeList eventL = item.ChildNodes;
  675. foreach (XmlNode evt in eventL)
  676. {
  677. switch (evt.Name)
  678. {
  679. case "Params":
  680. XmlNodeList prms = evt.ChildNodes;
  681. foreach (XmlNode pm in prms)
  682. parms.Add(ReadXTypedValue(pm));
  683. break;
  684. case "Detected":
  685. XmlNodeList detL = evt.ChildNodes;
  686. foreach (XmlNode det in detL)
  687. {
  688. string vect = det.Attributes.GetNamedItem("pos").Value;
  689. LSL_Vector v = new LSL_Vector(vect);
  690. int d_linkNum = 0;
  691. UUID d_group = UUID.Zero;
  692. string d_name = String.Empty;
  693. UUID d_owner = UUID.Zero;
  694. LSL_Vector d_position = new LSL_Vector();
  695. LSL_Rotation d_rotation = new LSL_Rotation();
  696. int d_type = 0;
  697. LSL_Vector d_velocity = new LSL_Vector();
  698. try
  699. {
  700. string tmp;
  701. tmp = det.Attributes.GetNamedItem("linkNum").Value;
  702. int.TryParse(tmp, out d_linkNum);
  703. tmp = det.Attributes.GetNamedItem("group").Value;
  704. UUID.TryParse(tmp, out d_group);
  705. d_name = det.Attributes.GetNamedItem("name").Value;
  706. tmp = det.Attributes.GetNamedItem("owner").Value;
  707. UUID.TryParse(tmp, out d_owner);
  708. tmp = det.Attributes.GetNamedItem("position").Value;
  709. d_position = new LSL_Types.Vector3(tmp);
  710. tmp = det.Attributes.GetNamedItem("rotation").Value;
  711. d_rotation = new LSL_Rotation(tmp);
  712. tmp = det.Attributes.GetNamedItem("type").Value;
  713. int.TryParse(tmp, out d_type);
  714. tmp = det.Attributes.GetNamedItem("velocity").Value;
  715. d_velocity = new LSL_Vector(tmp);
  716. }
  717. catch (Exception) // Old version XML
  718. {
  719. }
  720. UUID uuid = new UUID();
  721. UUID.TryParse(det.InnerText, out uuid);
  722. DetectParams d = new DetectParams();
  723. d.Key = uuid;
  724. d.OffsetPos = v;
  725. d.LinkNum = d_linkNum;
  726. d.Group = d_group;
  727. d.Name = d_name;
  728. d.Owner = d_owner;
  729. d.Position = d_position;
  730. d.Rotation = d_rotation;
  731. d.Type = d_type;
  732. d.Velocity = d_velocity;
  733. detected.Add(d);
  734. }
  735. break;
  736. }
  737. }
  738. EventParams ep = new EventParams(
  739. eventName, parms.ToArray(),
  740. detected.ToArray());
  741. eventQueue.AddLast(ep);
  742. }
  743. break;
  744. case "Plugins":
  745. List<Object> olist = new List<Object>();
  746. XmlNodeList itemLP = part.ChildNodes;
  747. foreach (XmlNode item in itemLP)
  748. olist.Add(ReadXTypedValue(item));
  749. pluginData = olist.ToArray();
  750. break;
  751. case "Permissions":
  752. string tmpPerm;
  753. int mask = 0;
  754. tmpPerm = part.Attributes.GetNamedItem("mask").Value;
  755. if (tmpPerm != null)
  756. {
  757. int.TryParse(tmpPerm, out mask);
  758. if (mask != 0)
  759. {
  760. tmpPerm = part.Attributes.GetNamedItem("granter").Value;
  761. if (tmpPerm != null)
  762. {
  763. UUID granter = new UUID();
  764. UUID.TryParse(tmpPerm, out granter);
  765. if (granter != UUID.Zero)
  766. {
  767. permsMask = mask;
  768. permsGranter = granter;
  769. }
  770. }
  771. }
  772. }
  773. break;
  774. case "MinEventDelay":
  775. double.TryParse(part.InnerText, out minEventDelay);
  776. break;
  777. }
  778. }
  779. }
  780. catch
  781. {
  782. throw new Exception("Xstate fail decode");
  783. }
  784. int k = 0;
  785. stateCode = 0;
  786. foreach (string sn in m_ObjCode.stateNames)
  787. {
  788. if (stateName == sn)
  789. {
  790. stateCode = k;
  791. break;
  792. }
  793. k++;
  794. }
  795. eventCode = ScriptEventCode.None;
  796. m_Running = running;
  797. doGblInit = false;
  798. m_Item.PermsGranter = permsGranter;
  799. m_Item.PermsMask = permsMask;
  800. m_Part.Inventory.UpdateInventoryItem(m_Item, false, false);
  801. lock (m_RunLock)
  802. {
  803. glblVars.iarIntegers = ints;
  804. glblVars.iarFloats = doubles;
  805. glblVars.iarVectors = vectors;
  806. glblVars.iarRotations = rotations;
  807. glblVars.iarStrings = strings;
  808. glblVars.iarLists = lists;
  809. AddArraysHeapUse(heapsz);
  810. CheckRunLockInvariants(true);
  811. }
  812. lock (m_QueueLock)
  813. {
  814. m_DetectParams = null;
  815. foreach (EventParams evt in m_EventQueue)
  816. eventQueue.AddLast(evt);
  817. m_EventQueue = eventQueue;
  818. for (int i = m_EventCounts.Length; --i >= 0;)
  819. m_EventCounts[i] = 0;
  820. foreach (EventParams evt in m_EventQueue)
  821. {
  822. if(m_eventCodeMap.TryGetValue(evt.EventName, out ScriptEventCode evtCode))
  823. m_EventCounts[(int)evtCode]++;
  824. }
  825. }
  826. AsyncCommandManager.CreateFromData(m_Engine,
  827. m_LocalID, m_ItemID, m_Part.UUID, pluginData);
  828. MinEventDelay = minEventDelay;
  829. }
  830. private static void getvarNames(Dictionary<int, string> s, Dictionary<string, int> d)
  831. {
  832. foreach(KeyValuePair<int, string> kvp in s)
  833. d[kvp.Value] = kvp.Key;
  834. }
  835. private static LSL_Types.list ReadXList(XmlNode parent)
  836. {
  837. List<Object> olist = new List<Object>();
  838. XmlNodeList itemL = parent.ChildNodes;
  839. foreach (XmlNode item in itemL)
  840. olist.Add(ReadXTypedValue(item));
  841. return new LSL_Types.list(olist.ToArray());
  842. }
  843. private static object ReadXTypedValue(XmlNode tag, out string name)
  844. {
  845. name = tag.Attributes.GetNamedItem("name").Value;
  846. return ReadXTypedValue(tag);
  847. }
  848. private static object ReadXTypedValue(XmlNode tag)
  849. {
  850. Object varValue;
  851. string assembly;
  852. string itemType = tag.Attributes.GetNamedItem("type").Value;
  853. if (itemType == "list")
  854. return ReadXList(tag);
  855. if (itemType == "OpenMetaverse.UUID")
  856. {
  857. UUID val = new UUID();
  858. UUID.TryParse(tag.InnerText, out val);
  859. return val;
  860. }
  861. Type itemT = Type.GetType(itemType);
  862. if (itemT == null)
  863. {
  864. Object[] args =
  865. new Object[] { tag.InnerText };
  866. assembly = itemType + ", OpenSim.Region.ScriptEngine.Shared";
  867. itemT = Type.GetType(assembly);
  868. if (itemT == null)
  869. return null;
  870. varValue = Activator.CreateInstance(itemT, args);
  871. if (varValue == null)
  872. return null;
  873. }
  874. else
  875. {
  876. varValue = Convert.ChangeType(tag.InnerText, itemT);
  877. }
  878. return varValue;
  879. }
  880. /**
  881. * @brief Read llDetectedGrab, etc, values from XML
  882. * <EventQueue>
  883. * <DetectParams>...</DetectParams>
  884. * .
  885. * .
  886. * .
  887. * </EventQueue>
  888. */
  889. private LinkedList<EventParams> RestoreEventQueue(XmlNode eventsN)
  890. {
  891. LinkedList<EventParams> eventQueue = new LinkedList<EventParams>();
  892. if(eventsN != null)
  893. {
  894. XmlNodeList eventL = eventsN.SelectNodes("Event");
  895. foreach(XmlNode evnt in eventL)
  896. {
  897. string name = ((XmlElement)evnt).GetAttribute("Name");
  898. object[] parms = ExtractXMLObjectArray(evnt, "param");
  899. DetectParams[] detects = RestoreDetectParams(evnt);
  900. if(parms == null)
  901. parms = zeroObjectArray;
  902. if(detects == null)
  903. detects = zeroDetectParams;
  904. EventParams evt = new EventParams(name, parms, detects);
  905. eventQueue.AddLast(evt);
  906. }
  907. }
  908. return eventQueue;
  909. }
  910. /**
  911. * @brief Read llDetectedGrab, etc, values from XML
  912. * <DetectArray>
  913. * <DetectParams>...</DetectParams>
  914. * .
  915. * .
  916. * .
  917. * </DetectArray>
  918. */
  919. private DetectParams[] RestoreDetectParams(XmlNode detectedN)
  920. {
  921. if(detectedN == null)
  922. return null;
  923. List<DetectParams> detected = new List<DetectParams>();
  924. XmlNodeList detectL = detectedN.SelectNodes("DetectParams");
  925. DetectParams detprm = new DetectParams();
  926. foreach(XmlNode detxml in detectL)
  927. {
  928. try
  929. {
  930. detprm.Group = new UUID(detxml.Attributes.GetNamedItem("group").Value);
  931. detprm.Key = new UUID(detxml.Attributes.GetNamedItem("key").Value);
  932. detprm.Owner = new UUID(detxml.Attributes.GetNamedItem("owner").Value);
  933. detprm.LinkNum = Int32.Parse(detxml.Attributes.GetNamedItem("linkNum").Value);
  934. detprm.Type = Int32.Parse(detxml.Attributes.GetNamedItem("type").Value);
  935. detprm.Name = detxml.Attributes.GetNamedItem("name").Value;
  936. detprm.OffsetPos = new LSL_Types.Vector3(detxml.Attributes.GetNamedItem("pos").Value);
  937. detprm.Position = new LSL_Types.Vector3(detxml.Attributes.GetNamedItem("position").Value);
  938. detprm.Velocity = new LSL_Types.Vector3(detxml.Attributes.GetNamedItem("velocity").Value);
  939. detprm.Rotation = new LSL_Types.Quaternion(detxml.Attributes.GetNamedItem("rotation").Value);
  940. detected.Add(detprm);
  941. detprm = new DetectParams();
  942. }
  943. catch(Exception e)
  944. {
  945. m_log.Warn("[YEngine]: RestoreDetectParams bad XML: " + detxml.ToString());
  946. m_log.Warn("[YEngine]: ... " + e.ToString());
  947. }
  948. }
  949. return detected.ToArray();
  950. }
  951. /**
  952. * @brief Extract elements of an array of objects from an XML parent.
  953. * Each element is of form <tag ...>...</tag>
  954. * @param parent = XML parent to extract them from
  955. * @param tag = what the value's tag is
  956. * @returns object array of the values
  957. */
  958. private static object[] ExtractXMLObjectArray(XmlNode parent, string tag)
  959. {
  960. List<Object> olist = new List<Object>();
  961. XmlNodeList itemL = parent.SelectNodes(tag);
  962. foreach(XmlNode item in itemL)
  963. {
  964. olist.Add(ExtractXMLObjectValue(item));
  965. }
  966. return olist.ToArray();
  967. }
  968. private static object ExtractXMLObjectValue(XmlNode item)
  969. {
  970. string itemType = item.Attributes.GetNamedItem("type").Value;
  971. if(itemType == "list")
  972. {
  973. return new LSL_List(ExtractXMLObjectArray(item, "item"));
  974. }
  975. if(itemType == "OpenMetaverse.UUID")
  976. {
  977. UUID val = new UUID();
  978. UUID.TryParse(item.InnerText, out val);
  979. return val;
  980. }
  981. Type itemT = Type.GetType(itemType);
  982. if(itemT == null)
  983. {
  984. Object[] args = new Object[] { item.InnerText };
  985. string assembly = itemType + ", OpenSim.Region.ScriptEngine.Shared";
  986. itemT = Type.GetType(assembly);
  987. if(itemT == null)
  988. {
  989. return null;
  990. }
  991. return Activator.CreateInstance(itemT, args);
  992. }
  993. return Convert.ChangeType(item.InnerText, itemT);
  994. }
  995. /*
  996. * Migrate an event handler in from a stream.
  997. *
  998. * Input:
  999. * stream = as generated by MigrateOutEventHandler()
  1000. */
  1001. private void MigrateInEventHandler(Stream stream)
  1002. {
  1003. int mv = stream.ReadByte();
  1004. if(mv != migrationVersion)
  1005. throw new Exception("incoming migration version " + mv + " but accept only " + migrationVersion);
  1006. stream.ReadByte(); // ignored
  1007. /*
  1008. * Restore script variables and stack and other state from stream.
  1009. * And it also marks us busy (by setting this.eventCode) so we can't be
  1010. * started again and this event lost. If it restores this.eventCode =
  1011. * None, the the script was idle.
  1012. */
  1013. lock(m_RunLock)
  1014. {
  1015. BinaryReader br = new BinaryReader(stream);
  1016. this.MigrateIn(br);
  1017. m_RunOnePhase = "MigrateInEventHandler finished";
  1018. CheckRunLockInvariants(true);
  1019. }
  1020. }
  1021. }
  1022. }