aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs295
1 files changed, 295 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs
new file mode 100644
index 0000000..94241eb
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/LSLLongCmdHandler.cs
@@ -0,0 +1,295 @@
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 OpenSim 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*/
28
29using System;
30using System.Collections.Generic;
31using System.Threading;
32using libsecondlife;
33using OpenSim.Region.Environment.Interfaces;
34using OpenSim.Region.Environment.Modules;
35
36namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
37{
38 /// <summary>
39 /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
40 /// </summary>
41 public class LSLLongCmdHandler
42 {
43 private Thread cmdHandlerThread;
44 private int cmdHandlerThreadCycleSleepms = 100;
45
46 private ScriptEngine m_ScriptEngine;
47
48 public LSLLongCmdHandler(ScriptEngine _ScriptEngine)
49 {
50 m_ScriptEngine = _ScriptEngine;
51
52 // Start the thread that will be doing the work
53 cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
54 cmdHandlerThread.Name = "CmdHandlerThread";
55 cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
56 cmdHandlerThread.IsBackground = true;
57 cmdHandlerThread.Start();
58 }
59
60 ~LSLLongCmdHandler()
61 {
62 // Shut down thread
63 try
64 {
65 if (cmdHandlerThread != null)
66 {
67 if (cmdHandlerThread.IsAlive == true)
68 {
69 cmdHandlerThread.Abort();
70 cmdHandlerThread.Join();
71 }
72 }
73 }
74 catch
75 {
76 }
77 }
78
79 private void CmdHandlerThreadLoop()
80 {
81 while (true)
82 {
83 // Check timers
84 CheckTimerEvents();
85 Thread.Sleep(25);
86 // Check HttpRequests
87 CheckHttpRequests();
88 Thread.Sleep(25);
89 // Check XMLRPCRequests
90 CheckXMLRPCRequests();
91 Thread.Sleep(25);
92 // Check Listeners
93 CheckListeners();
94 Thread.Sleep(25);
95
96 // Sleep before next cycle
97 //Thread.Sleep(cmdHandlerThreadCycleSleepms);
98 }
99 }
100
101 /// <summary>
102 /// Remove a specific script (and all its pending commands)
103 /// </summary>
104 /// <param name="m_localID"></param>
105 /// <param name="m_itemID"></param>
106 public void RemoveScript(uint localID, LLUUID itemID)
107 {
108 // Remove a specific script
109
110 // Remove from: Timers
111 UnSetTimerEvents(localID, itemID);
112 // Remove from: HttpRequest
113 IHttpRequests iHttpReq =
114 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
115 iHttpReq.StopHttpRequest(localID, itemID);
116 }
117
118 #region TIMER
119
120 //
121 // TIMER
122 //
123 private class TimerClass
124 {
125 public uint localID;
126 public LLUUID itemID;
127 public double interval;
128 public DateTime next;
129 }
130
131 private List<TimerClass> Timers = new List<TimerClass>();
132 private object TimerListLock = new object();
133
134 public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec)
135 {
136 Console.WriteLine("SetTimerEvent");
137
138 // Always remove first, in case this is a re-set
139 UnSetTimerEvents(m_localID, m_itemID);
140 if (sec == 0) // Disabling timer
141 return;
142
143 // Add to timer
144 TimerClass ts = new TimerClass();
145 ts.localID = m_localID;
146 ts.itemID = m_itemID;
147 ts.interval = sec;
148 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
149 lock (TimerListLock)
150 {
151 Timers.Add(ts);
152 }
153 }
154
155 public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID)
156 {
157 // Remove from timer
158 lock (TimerListLock)
159 {
160 List<TimerClass> NewTimers = new List<TimerClass>();
161 foreach (TimerClass ts in Timers)
162 {
163 if (ts.localID != m_localID && ts.itemID != m_itemID)
164 {
165 NewTimers.Add(ts);
166 }
167 }
168 Timers.Clear();
169 Timers = NewTimers;
170 }
171 }
172
173 public void CheckTimerEvents()
174 {
175 // Nothing to do here?
176 if (Timers.Count == 0)
177 return;
178
179 lock (TimerListLock)
180 {
181 // Go through all timers
182 foreach (TimerClass ts in Timers)
183 {
184 // Time has passed?
185 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
186 {
187 // Add it to queue
188 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer",
189 new object[] {});
190 // set next interval
191
192
193 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
194 }
195 }
196 } // lock
197 }
198
199 #endregion
200
201 #region HTTP REQUEST
202
203 public void CheckHttpRequests()
204 {
205 if (m_ScriptEngine.World == null)
206 return;
207
208 IHttpRequests iHttpReq =
209 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
210
211 HttpRequestClass httpInfo = null;
212
213 if (iHttpReq != null)
214 httpInfo = iHttpReq.GetNextCompletedRequest();
215
216 while (httpInfo != null)
217 {
218 //Console.WriteLine("PICKED HTTP REQ:" + httpInfo.response_body + httpInfo.status);
219
220 // Deliver data to prim's remote_data handler
221 //
222 // TODO: Returning null for metadata, since the lsl function
223 // only returns the byte for HTTP_BODY_TRUNCATED, which is not
224 // implemented here yet anyway. Should be fixed if/when maxsize
225 // is supported
226
227 object[] resobj = new object[]
228 {
229 httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body
230 };
231
232 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
233 httpInfo.localID, httpInfo.itemID, "http_response", resobj
234 );
235
236 httpInfo.Stop();
237 httpInfo = null;
238
239 httpInfo = iHttpReq.GetNextCompletedRequest();
240 }
241 }
242
243 #endregion
244
245 public void CheckXMLRPCRequests()
246 {
247 if (m_ScriptEngine.World == null)
248 return;
249
250 IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
251
252 if (xmlrpc != null)
253 {
254 while (xmlrpc.hasRequests())
255 {
256 RPCRequestInfo rInfo = xmlrpc.GetNextRequest();
257 //Console.WriteLine("PICKED REQUEST");
258
259 //Deliver data to prim's remote_data handler
260 object[] resobj = new object[]
261 {
262 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), "",
263 rInfo.GetIntValue(),
264 rInfo.GetStrVal()
265 };
266 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
267 rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", resobj
268 );
269 }
270 }
271 }
272
273 public void CheckListeners()
274 {
275 if (m_ScriptEngine.World == null)
276 return;
277 IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
278
279 while (comms.HasMessages())
280 {
281 ListenerInfo lInfo = comms.GetNextMessage();
282
283 //Deliver data to prim's listen handler
284 object[] resobj = new object[]
285 {
286 lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage()
287 };
288
289 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
290 lInfo.GetLocalID(), lInfo.GetItemID(), "listen", resobj
291 );
292 }
293 }
294 }
295} \ No newline at end of file