aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorSean Dague2007-10-05 19:33:26 +0000
committerSean Dague2007-10-05 19:33:26 +0000
commit29aa41daa004531cc41649c1818e4e432600cc32 (patch)
tree6d2e3574b7222137a83fc6ba6502b197efb89bfc
parentgetting all our line endings consistant again (diff)
downloadopensim-SC_OLD-29aa41daa004531cc41649c1818e4e432600cc32.zip
opensim-SC_OLD-29aa41daa004531cc41649c1818e4e432600cc32.tar.gz
opensim-SC_OLD-29aa41daa004531cc41649c1818e4e432600cc32.tar.bz2
opensim-SC_OLD-29aa41daa004531cc41649c1818e4e432600cc32.tar.xz
Code from Illumious Beltran (IBM) implementing more LSL
The functions implemented are: llListen llListenControl llListenRemove llOpenRemoteDataChannel llCloseRemoteDataChannel llRemoteDataReply The events implemented are: listen remote_data
-rw-r--r--OpenSim/Region/Environment/Interfaces/IWorldComm.cs15
-rw-r--r--OpenSim/Region/Environment/Interfaces/IXMLRPC.cs14
-rw-r--r--OpenSim/Region/Environment/ModuleLoader.cs8
-rw-r--r--OpenSim/Region/Environment/Modules/WorldCommModule.cs481
-rw-r--r--OpenSim/Region/Environment/Modules/XMLRPCModule.cs360
-rw-r--r--OpenSim/Region/Environment/Scenes/Scene.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs67
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs61
-rw-r--r--prebuild.xml1
9 files changed, 1002 insertions, 9 deletions
diff --git a/OpenSim/Region/Environment/Interfaces/IWorldComm.cs b/OpenSim/Region/Environment/Interfaces/IWorldComm.cs
new file mode 100644
index 0000000..23bdbb6
--- /dev/null
+++ b/OpenSim/Region/Environment/Interfaces/IWorldComm.cs
@@ -0,0 +1,15 @@
1using libsecondlife;
2using OpenSim.Region.Environment.Modules;
3
4namespace OpenSim.Region.Environment.Interfaces
5{
6 public interface IWorldComm
7 {
8 int Listen(uint LocalID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg);
9 void DeliverMessage(string sourceItemID, int type, int channel, string name, string msg);
10 bool HasMessages();
11 ListenerInfo GetNextMessage();
12 void ListenControl(int handle, int active);
13 void ListenRemove(int handle);
14 }
15} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Interfaces/IXMLRPC.cs b/OpenSim/Region/Environment/Interfaces/IXMLRPC.cs
new file mode 100644
index 0000000..dc44a8f
--- /dev/null
+++ b/OpenSim/Region/Environment/Interfaces/IXMLRPC.cs
@@ -0,0 +1,14 @@
1using libsecondlife;
2using OpenSim.Region.Environment.Modules;
3
4namespace OpenSim.Region.Environment.Interfaces
5{
6 public interface IXMLRPC
7 {
8 LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID);
9 void CloseXMLRPCChannel(LLUUID channelKey);
10 bool hasRequests();
11 RPCRequestInfo GetNextRequest();
12 void RemoteDataReply(string channel, string message_id, string sdata, int idata);
13 }
14} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/ModuleLoader.cs b/OpenSim/Region/Environment/ModuleLoader.cs
index ce2a843..43c1aae 100644
--- a/OpenSim/Region/Environment/ModuleLoader.cs
+++ b/OpenSim/Region/Environment/ModuleLoader.cs
@@ -34,6 +34,12 @@ namespace OpenSim.Region.Environment
34 module = new AvatarProfilesModule(); 34 module = new AvatarProfilesModule();
35 InitialiseModule(module, scene); 35 InitialiseModule(module, scene);
36 36
37 module = new XMLRPCModule();
38 InitialiseModule(module, scene);
39
40 module = new WorldCommModule();
41 InitialiseModule(module, scene);
42
37 LoadRegionModule("OpenSim.Region.ExtensionsScriptModule.dll", "ExtensionsScriptingModule", scene); 43 LoadRegionModule("OpenSim.Region.ExtensionsScriptModule.dll", "ExtensionsScriptingModule", scene);
38 44
39 string lslPath = Path.Combine("ScriptEngines", "OpenSim.Region.ScriptEngine.DotNetEngine.dll"); 45 string lslPath = Path.Combine("ScriptEngines", "OpenSim.Region.ScriptEngine.DotNetEngine.dll");
@@ -153,4 +159,4 @@ namespace OpenSim.Region.Environment
153 LoadedAssemblys.Clear(); 159 LoadedAssemblys.Clear();
154 } 160 }
155 } 161 }
156} \ No newline at end of file 162}
diff --git a/OpenSim/Region/Environment/Modules/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/WorldCommModule.cs
new file mode 100644
index 0000000..c2ec699
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/WorldCommModule.cs
@@ -0,0 +1,481 @@
1using System;
2using System.IO;
3using System.Net.Sockets;
4using System.Text;
5using System.Threading;
6using libsecondlife;
7using OpenSim.Framework.Interfaces;
8using OpenSim.Framework.Utilities;
9using OpenSim.Region.Environment.Interfaces;
10using OpenSim.Region.Environment.Scenes;
11using OpenSim.Framework.Servers;
12using Nwc.XmlRpc;
13using System.Collections;
14using System.Collections.Generic;
15
16/*****************************************************
17 *
18 * WorldCommModule
19 *
20 *
21 * Holding place for world comms - basically llListen
22 * function implementation.
23 *
24 * lLListen(integer channel, string name, key id, string msg)
25 * The name, id, and msg arguments specify the filtering
26 * criteria. You can pass the empty string
27 * (or NULL_KEY for id) for these to set a completely
28 * open filter; this causes the listen() event handler to be
29 * invoked for all chat on the channel. To listen only
30 * for chat spoken by a specific object or avatar,
31 * specify the name and/or id arguments. To listen
32 * only for a specific command, specify the
33 * (case-sensitive) msg argument. If msg is not empty,
34 * listener will only hear strings which are exactly equal
35 * to msg. You can also use all the arguments to establish
36 * the most restrictive filtering criteria.
37 *
38 * It might be useful for each listener to maintain a message
39 * digest, with a list of recent messages by UUID. This can
40 * be used to prevent in-world repeater loops. However, the
41 * linden functions do not have this capability, so for now
42 * thats the way it works.
43 *
44 * **************************************************/
45namespace OpenSim.Region.Environment.Modules
46{
47 public class WorldCommModule : IRegionModule, IWorldComm
48 {
49 private Scene m_scene;
50 private object CommListLock = new object();
51 private string m_name = "WorldCommModule";
52 private ListenerManager m_listenerManager;
53 private Queue<ListenerInfo> m_pending;
54
55 public WorldCommModule()
56 {
57 }
58
59 public void Initialise(Scene scene)
60 {
61
62 m_scene = scene;
63 m_scene.RegisterModuleInterface<IWorldComm>(this);
64 m_listenerManager = new ListenerManager();
65 m_pending = new Queue<ListenerInfo>();
66 m_scene.EventManager.OnNewClient += NewClient;
67
68 }
69
70 public void PostInitialise()
71 {
72 }
73
74 public void CloseDown()
75 {
76 }
77
78 public string GetName()
79 {
80 return m_name;
81 }
82
83 public bool IsSharedModule()
84 {
85 return false;
86 }
87
88 public void NewClient(IClientAPI client)
89 {
90 client.OnChatFromViewer += DeliverClientMessage;
91 }
92
93 private void DeliverClientMessage(byte[] message, byte type, int channel, LLVector3 fromPos, string fromName,
94 LLUUID fromAgentID)
95 {
96 ASCIIEncoding ae = new ASCIIEncoding();
97
98 DeliverMessage(fromAgentID.ToString(), type, channel, fromName, ae.GetString(message));
99
100 }
101
102 public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
103 {
104 return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg);
105 }
106
107 public void ListenControl(int handle, int active)
108 {
109 if ( active == 1 )
110 m_listenerManager.Activate(handle);
111 else if ( active == 0 )
112 m_listenerManager.Dectivate(handle);
113
114 }
115
116 public void ListenRemove(int handle)
117 {
118 m_listenerManager.Remove(handle);
119 }
120
121 // This method scans nearby objects and determines if they are listeners,
122 // and if so if this message fits the filter. If it does, then
123 // enqueue the message for delivery to the objects listen event handler.
124 // Objects that do an llSay have their messages delivered here, and for
125 // nearby avatards, the SimChat function is used.
126 public void DeliverMessage(string sourceItemID, int type, int channel, string name, string msg)
127 {
128
129 SceneObjectPart source = null;
130 ScenePresence avatar = null;
131
132 source = m_scene.GetSceneObjectPart(new LLUUID(sourceItemID));
133 if (source == null)
134 {
135 avatar = m_scene.GetScenePresence(new LLUUID(sourceItemID));
136 }
137 if( (avatar != null) || (source != null) )
138 {
139 // Loop through the objects in the scene
140 // If they are in proximity, then if they are
141 // listeners, if so add them to the pending queue
142
143 foreach (LLUUID eb in m_scene.Entities.Keys)
144 {
145 EntityBase sPart;
146
147 m_scene.Entities.TryGetValue(eb, out sPart);
148
149 // Dont process if this message is from itself!
150 if (eb.ToString().Equals(sourceItemID) ||
151 sPart.UUID.ToString().Equals(sourceItemID) )
152 continue;
153
154 double dis = 0;
155
156 if (source != null)
157 dis = sPart.AbsolutePosition.GetDistanceTo(source.AbsolutePosition);
158 else
159 dis = sPart.AbsolutePosition.GetDistanceTo(avatar.AbsolutePosition);
160
161 switch (type)
162 {
163 case 0: // Whisper
164
165 if ((dis < 10) && (dis > -10))
166 {
167 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
168 sourceItemID, sPart.UUID, channel, name, msg
169 );
170 if (isListener != null)
171 {
172 m_pending.Enqueue(isListener);
173 }
174
175 }
176 break;
177
178 case 1: // Say
179
180 if ((dis < 30) && (dis > -30))
181 {
182 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
183 sourceItemID, sPart.UUID, channel, name, msg
184 );
185 if (isListener != null)
186 {
187 m_pending.Enqueue(isListener);
188 }
189
190 }
191 break;
192
193 case 2: // Shout
194 if ((dis < 100) && (dis > -100))
195 {
196 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
197 sourceItemID, sPart.UUID, channel, name, msg
198 );
199 if (isListener != null)
200 {
201 m_pending.Enqueue(isListener);
202 }
203
204 }
205 break;
206
207 case 0xff: // Broadcast
208 ListenerInfo isListen = m_listenerManager.IsListenerMatch(sourceItemID, eb, channel, name, msg);
209 if (isListen != null)
210 {
211 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
212 sourceItemID, sPart.UUID, channel, name, msg
213 );
214 if (isListener != null)
215 {
216 m_pending.Enqueue(isListener);
217 }
218 }
219 break;
220 }
221 };
222
223 }
224
225 }
226
227 public bool HasMessages()
228 {
229 return (m_pending.Count > 0);
230 }
231
232 public ListenerInfo GetNextMessage()
233 {
234
235 ListenerInfo li = null;
236
237 lock (CommListLock)
238 {
239 li = m_pending.Dequeue();
240 }
241
242 return li;
243
244 }
245
246 }
247
248 // hostID: the ID of the ScenePart
249 // itemID: the ID of the script host engine
250 // localID: local ID of host engine
251 public class ListenerManager
252 {
253 private Dictionary<int, ListenerInfo> m_listeners;
254 private object ListenersLock = new object();
255 private int m_MaxListeners = 100;
256
257 public ListenerManager()
258 {
259 m_listeners = new Dictionary<int, ListenerInfo>();
260 }
261
262 public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
263 {
264
265 if ( m_listeners.Count < m_MaxListeners )
266 {
267 ListenerInfo isListener = IsListenerMatch(LLUUID.Zero.ToString(), itemID, channel, name, msg);
268
269 if(isListener == null)
270 {
271 int newHandle = GetNewHandle();
272
273 if (newHandle > -1)
274 {
275
276 ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg);
277
278 lock (ListenersLock)
279 {
280 m_listeners.Add(newHandle, li);
281 }
282
283 return newHandle;
284 }
285
286 }
287
288 }
289
290 return -1;
291
292 }
293
294 public void Remove(int handle)
295 {
296 m_listeners.Remove(handle);
297 }
298
299 private int GetNewHandle()
300 {
301
302 for (int i = 0; i < int.MaxValue - 1; i++)
303 {
304 if (!m_listeners.ContainsKey(i))
305 return i;
306 }
307
308 return -1;
309
310 }
311
312 public bool IsListener(LLUUID hostID)
313 {
314
315 foreach (ListenerInfo li in m_listeners.Values)
316 {
317 if (li.GetHostID().Equals(hostID))
318 return true;
319 }
320
321 return false;
322
323 }
324
325 public void Activate(int handle)
326 {
327
328 ListenerInfo li;
329
330 if( m_listeners.TryGetValue(handle, out li) )
331 {
332 li.Activate();
333 }
334 }
335
336 public void Dectivate(int handle)
337 {
338
339 ListenerInfo li;
340
341 if( m_listeners.TryGetValue(handle, out li) )
342 {
343 li.Deactivate();
344 }
345 }
346
347 // Theres probably a more clever and efficient way to
348 // do this, maybe with regex.
349 public ListenerInfo IsListenerMatch(string sourceItemID, LLUUID listenerKey, int channel, string name, string msg)
350 {
351
352 bool isMatch = true;
353
354 foreach (ListenerInfo li in m_listeners.Values)
355 {
356 if (li.GetHostID().Equals(listenerKey))
357 {
358 if ( li.IsActive() )
359 {
360 if ( channel == li.GetChannel() )
361 {
362 if ( (li.GetID().ToString().Length > 0) &&
363 (!li.GetID().Equals(LLUUID.Zero)) )
364 {
365 if (!li.GetID().ToString().Equals(sourceItemID))
366 {
367 isMatch = false;
368 }
369 }
370 if ( isMatch && (li.GetName().Length > 0) )
371 {
372 if ( li.GetName().Equals(name) )
373 {
374 isMatch = false;
375 }
376 }
377 if ( isMatch )
378 {
379 return new ListenerInfo(
380 li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(),
381 li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID)
382 );
383 }
384 }
385 }
386 }
387 }
388 return null;
389 }
390
391 }
392
393 public class ListenerInfo
394 {
395
396 private LLUUID m_itemID; // ID of the host script engine
397 private LLUUID m_hostID; // ID of the host/scene part
398 private LLUUID m_sourceItemID; // ID of the scenePart or avatar source of the message
399 private int m_channel; // Channel
400 private int m_handle; // Assigned handle of this listener
401 private uint m_localID; // Local ID from script engine
402 private string m_name; // Object name to filter messages from
403 private LLUUID m_id; // ID to filter messages from
404 private string m_message; // The message
405 private bool m_active; // Listener is active or not
406
407 public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message)
408 {
409 Initialise(localID, handle, ItemID, hostID, channel, name, id, message);
410 }
411
412 public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message, LLUUID sourceItemID)
413 {
414 Initialise(localID, handle, ItemID, hostID, channel, name, id, message);
415 m_sourceItemID = sourceItemID;
416 }
417
418 private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message)
419 {
420 m_handle = handle;
421 m_channel = channel;
422 m_itemID = ItemID;
423 m_hostID = hostID;
424 m_name = name;
425 m_id = id;
426 m_message = message;
427 m_active = true;
428 m_localID = localID;
429 }
430 public LLUUID GetItemID()
431 {
432 return m_itemID;
433 }
434 public LLUUID GetHostID()
435 {
436 return m_hostID;
437 }
438 public LLUUID GetSourceItemID()
439 {
440 return m_sourceItemID;
441 }
442 public int GetChannel()
443 {
444 return m_channel;
445 }
446 public uint GetLocalID()
447 {
448 return m_localID;
449 }
450 public int GetHandle()
451 {
452 return m_handle;
453 }
454 public string GetMessage()
455 {
456 return m_message;
457 }
458 public string GetName()
459 {
460 return m_name;
461 }
462 public bool IsActive()
463 {
464 return m_active;
465 }
466 public void Deactivate()
467 {
468 m_active = false;
469 }
470 public void Activate()
471 {
472 m_active = true;
473 }
474 public LLUUID GetID()
475 {
476 return m_id;
477 }
478
479 }
480
481}
diff --git a/OpenSim/Region/Environment/Modules/XMLRPCModule.cs b/OpenSim/Region/Environment/Modules/XMLRPCModule.cs
new file mode 100644
index 0000000..50ed776
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/XMLRPCModule.cs
@@ -0,0 +1,360 @@
1using System;
2using System.IO;
3using System.Net.Sockets;
4using System.Threading;
5using libsecondlife;
6using OpenSim.Framework.Interfaces;
7using OpenSim.Framework.Utilities;
8using OpenSim.Region.Environment.Interfaces;
9using OpenSim.Region.Environment.Scenes;
10using OpenSim.Framework.Servers;
11using Nwc.XmlRpc;
12using System.Collections;
13using System.Collections.Generic;
14
15/*****************************************************
16 *
17 * XMLRPCModule
18 *
19 * Module for accepting incoming communications from
20 * external XMLRPC client and calling a remote data
21 * procedure for a registered data channel/prim.
22 *
23 *
24 * 1. On module load, open a listener port
25 * 2. Attach an XMLRPC handler
26 * 3. When a request is received:
27 * 3.1 Parse into components: channel key, int, string
28 * 3.2 Look up registered channel listeners
29 * 3.3 Call the channel (prim) remote data method
30 * 3.4 Capture the response (llRemoteDataReply)
31 * 3.5 Return response to client caller
32 * 3.6 If no response from llRemoteDataReply within
33 * RemoteReplyScriptTimeout, generate script timeout fault
34 *
35 * Prims in script must:
36 * 1. Open a remote data channel
37 * 1.1 Generate a channel ID
38 * 1.2 Register primid,channelid pair with module
39 * 2. Implement the remote data procedure handler
40 *
41 * llOpenRemoteDataChannel
42 * llRemoteDataReply
43 * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval)
44 * llCloseRemoteDataChannel
45 *
46 * **************************************************/
47namespace OpenSim.Region.Environment.Modules
48{
49 public class XMLRPCModule : IRegionModule, IXMLRPC
50 {
51 private Scene m_scene;
52 private Queue<RPCRequestInfo> rpcQueue = new Queue<RPCRequestInfo>();
53 private object XMLRPCListLock = new object();
54 private string m_name = "XMLRPCModule";
55 private int RemoteReplyScriptWait = 100;
56 private int RemoteReplyScriptTimeout = 300;
57
58 // <channel id, RPCChannelInfo>
59 private Dictionary<LLUUID, RPCChannelInfo> m_openChannels;
60
61 // <channel id, RPCRequestInfo>
62 private Dictionary<LLUUID, RPCRequestInfo> m_pendingResponse;
63
64 public XMLRPCModule()
65 {
66 }
67
68 public void Initialise(Scene scene)
69 {
70 m_scene = scene;
71
72 m_scene.RegisterModuleInterface<IXMLRPC>(this);
73
74 m_openChannels = new Dictionary<LLUUID, RPCChannelInfo>();
75 m_pendingResponse = new Dictionary<LLUUID, RPCRequestInfo>();
76
77 // Start http server
78 // Attach xmlrpc handlers
79 BaseHttpServer httpServer = new BaseHttpServer(20800);
80 httpServer.AddXmlRPCHandler("llRemoteData", this.XmlRpcRemoteData);
81 httpServer.Start();
82 }
83
84 public void PostInitialise()
85 {
86 }
87
88 public void CloseDown()
89 {
90 }
91
92 public string GetName()
93 {
94 return m_name;
95 }
96
97 public bool IsSharedModule()
98 {
99 return false;
100 }
101
102 /**********************************************
103 * OpenXMLRPCChannel
104 *
105 * Generate a LLUUID channel key and add it and
106 * the prim id to dictionary <channelUUID, primUUID>
107 *
108 * First check if there is a channel assigned for
109 * this itemID. If there is, then someone called
110 * llOpenRemoteDataChannel twice. Just return the
111 * original channel. Other option is to delete the
112 * current channel and assign a new one.
113 *
114 * ********************************************/
115 public LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID)
116 {
117 LLUUID channel = null;
118
119 //Is a dupe?
120 foreach (RPCChannelInfo ci in m_openChannels.Values)
121 {
122 if (ci.GetItemID().Equals(itemID))
123 {
124 // return the original channel ID for this item
125 channel = ci.GetChannelID();
126 break;
127 }
128 }
129
130 if ( (channel == null) || (channel.Equals(LLUUID.Zero)) )
131 {
132 channel = LLUUID.Random();
133 RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, channel);
134 lock (XMLRPCListLock)
135 {
136 m_openChannels.Add(channel, rpcChanInfo);
137 }
138
139 }
140
141 return channel;
142 }
143
144 /**********************************************
145 * Remote Data Reply
146 *
147 * Response to RPC message
148 *
149 *********************************************/
150 public void RemoteDataReply(string channel, string message_id, string sdata, int idata)
151 {
152 RPCRequestInfo rpcInfo;
153 LLUUID message_key = new LLUUID(message_id);
154
155 if (m_pendingResponse.TryGetValue(message_key, out rpcInfo))
156 {
157 rpcInfo.SetRetval(sdata);
158 rpcInfo.SetProcessed(true);
159
160 lock (XMLRPCListLock)
161 {
162 m_pendingResponse.Remove(message_key);
163 }
164 }
165
166 }
167
168 /**********************************************
169 * CloseXMLRPCChannel
170 *
171 * Remove channel from dictionary
172 *
173 *********************************************/
174 public void CloseXMLRPCChannel(LLUUID channelKey)
175 {
176 if(m_openChannels.ContainsKey(channelKey))
177 m_openChannels.Remove(channelKey);
178 }
179
180
181 public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request)
182 {
183
184 XmlRpcResponse response = new XmlRpcResponse();
185
186 Hashtable requestData = (Hashtable)request.Params[0];
187 bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") && requestData.Contains("StringValue"));
188
189 if (GoodXML)
190 {
191 LLUUID channel = new LLUUID((string)requestData["Channel"]);
192 RPCChannelInfo rpcChanInfo;
193 if (m_openChannels.TryGetValue(channel, out rpcChanInfo))
194 {
195 string intVal = (string)requestData["IntValue"];
196 string strVal = (string)requestData["StringValue"];
197
198 RPCRequestInfo rpcInfo;
199
200 lock (XMLRPCListLock)
201 {
202 rpcInfo = new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal, intVal);
203 rpcQueue.Enqueue(rpcInfo);
204 }
205
206 int timeoutCtr = 0;
207
208 while(!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout))
209 {
210 Thread.Sleep(RemoteReplyScriptWait);
211 timeoutCtr += RemoteReplyScriptWait;
212 }
213 if (rpcInfo.IsProcessed())
214 {
215 response.Value = rpcInfo.GetRetval();
216 rpcInfo = null;
217 }
218 else
219 {
220 response.SetFault(-1, "Script timeout");
221 lock (XMLRPCListLock)
222 {
223 m_pendingResponse.Remove(rpcInfo.GetMessageID());
224 }
225 }
226
227 }
228 else
229 {
230 response.SetFault(-1, "Invalid channel");
231 }
232
233 }
234
235 return response;
236 }
237
238 public bool hasRequests()
239 {
240 return (rpcQueue.Count > 0);
241 }
242
243 public RPCRequestInfo GetNextRequest()
244 {
245 lock (XMLRPCListLock)
246 {
247 RPCRequestInfo rpcInfo = rpcQueue.Dequeue();
248 m_pendingResponse.Add(rpcInfo.GetMessageID(), rpcInfo);
249 return rpcInfo;
250 }
251 }
252
253 }
254
255 /**************************************************************
256 *
257 * Class RPCRequestInfo
258 *
259 * Holds details about incoming requests until they are picked
260 * from the queue by LSLLongCmdHandler
261 * ***********************************************************/
262 public class RPCRequestInfo
263 {
264 private string m_StrVal;
265 private string m_IntVal;
266 private bool m_processed;
267 private string m_resp;
268 private uint m_localID;
269 private LLUUID m_ItemID;
270 private LLUUID m_MessageID;
271 private LLUUID m_ChannelKey;
272
273 public RPCRequestInfo(uint localID, LLUUID itemID, LLUUID channelKey, string strVal, string intVal)
274 {
275 m_localID = localID;
276 m_StrVal = strVal;
277 m_IntVal = intVal;
278 m_ItemID = itemID;
279 m_ChannelKey = channelKey;
280 m_MessageID = LLUUID.Random();
281 m_processed = false;
282 m_resp = "";
283 }
284
285 public bool IsProcessed()
286 {
287 return m_processed;
288 }
289 public LLUUID GetChannelKey()
290 {
291 return m_ChannelKey;
292 }
293
294 public void SetProcessed(bool processed)
295 {
296 m_processed = processed;
297 }
298 public void SetRetval(string resp)
299 {
300 m_resp = resp;
301 }
302 public string GetRetval()
303 {
304 return m_resp;
305 }
306 public uint GetLocalID()
307 {
308 return m_localID;
309 }
310 public LLUUID GetItemID()
311 {
312 return m_ItemID;
313 }
314 public string GetStrVal()
315 {
316 return m_StrVal;
317 }
318 public int GetIntValue()
319 {
320 return int.Parse(m_IntVal);
321 }
322 public LLUUID GetMessageID()
323 {
324 return m_MessageID;
325 }
326
327
328 }
329
330 public class RPCChannelInfo
331 {
332 private LLUUID m_itemID;
333 private uint m_localID;
334 private LLUUID m_ChannelKey;
335
336 public RPCChannelInfo(uint localID, LLUUID itemID, LLUUID channelID)
337 {
338 m_ChannelKey = channelID;
339 m_localID = localID;
340 m_itemID = itemID;
341 }
342
343 public LLUUID GetItemID()
344 {
345 return m_itemID;
346 }
347
348 public LLUUID GetChannelID()
349 {
350 return m_ChannelKey;
351 }
352
353 public uint GetLocalID()
354 {
355 return m_localID;
356 }
357
358 }
359
360}
diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs
index 579ec90..9e19a26 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.cs
@@ -91,6 +91,8 @@ namespace OpenSim.Region.Environment.Scenes
91 91
92 private IHttpRequests m_httpRequestModule = null; 92 private IHttpRequests m_httpRequestModule = null;
93 private ISimChat m_simChatModule = null; 93 private ISimChat m_simChatModule = null;
94 private IXMLRPC m_xmlrpcModule = null;
95 private IWorldComm m_worldCommModule = null;
94 96
95 97
96 // Central Update Loop 98 // Central Update Loop
@@ -210,6 +212,8 @@ namespace OpenSim.Region.Environment.Scenes
210 { 212 {
211 m_simChatModule = RequestModuleInterface<ISimChat>(); 213 m_simChatModule = RequestModuleInterface<ISimChat>();
212 m_httpRequestModule = RequestModuleInterface<IHttpRequests>(); 214 m_httpRequestModule = RequestModuleInterface<IHttpRequests>();
215 m_xmlrpcModule = RequestModuleInterface<IXMLRPC>();
216 m_worldCommModule = RequestModuleInterface<IWorldComm>();
213 217
214 XferManager = RequestModuleInterface<IXfer>(); 218 XferManager = RequestModuleInterface<IXfer>();
215 } 219 }
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs
index 6838f47..3985273 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs
@@ -177,14 +177,19 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
177 //type for whisper is 0 177 //type for whisper is 0
178 World.SimChat(Helpers.StringToField(text), 178 World.SimChat(Helpers.StringToField(text),
179 0, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); 179 0, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID);
180
181 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
182 wComm.DeliverMessage(m_host.UUID.ToString(), 0, channelID, m_host.Name, text);
180 } 183 }
181 184
182 public void llSay(int channelID, string text) 185 public void llSay(int channelID, string text)
183 { 186 {
184 //type for say is 1 187 //type for say is 1
185
186 World.SimChat(Helpers.StringToField(text), 188 World.SimChat(Helpers.StringToField(text),
187 1, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); 189 1, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID);
190
191 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
192 wComm.DeliverMessage(m_host.UUID.ToString(), 1, channelID, m_host.Name, text);
188 } 193 }
189 194
190 public void llShout(int channelID, string text) 195 public void llShout(int channelID, string text)
@@ -192,11 +197,32 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
192 //type for shout is 2 197 //type for shout is 2
193 World.SimChat(Helpers.StringToField(text), 198 World.SimChat(Helpers.StringToField(text),
194 2, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID); 199 2, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID);
200
201 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
202 wComm.DeliverMessage(m_host.UUID.ToString(), 2, channelID, m_host.Name, text);
203 }
204
205 public int llListen(int channelID, string name, string ID, string msg) {
206
207 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
208 return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, ID, msg);
209
210 }
211
212 public void llListenControl(int number, int active) {
213
214 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
215 wComm.ListenControl(number, active);
216
217 }
218
219 public void llListenRemove(int number) {
220
221 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
222 wComm.ListenRemove(number);
223
195 } 224 }
196 225
197 public int llListen(int channelID, string name, string ID, string msg) { NotImplemented("llListen"); return 0; }
198 public void llListenControl(int number, int active) { NotImplemented("llListenControl"); return; }
199 public void llListenRemove(int number) { NotImplemented("llListenRemove"); return; }
200 public void llSensor(string name, string id, int type, double range, double arc) { NotImplemented("llSensor"); return; } 226 public void llSensor(string name, string id, int type, double range, double arc) { NotImplemented("llSensor"); return; }
201 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) { NotImplemented("llSensorRepeat"); return; } 227 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) { NotImplemented("llSensorRepeat"); return; }
202 public void llSensorRemove() { NotImplemented("llSensorRemove"); return; } 228 public void llSensorRemove() { NotImplemented("llSensorRemove"); return; }
@@ -927,10 +953,37 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler
927 public void llRemoteLoadScript() { NotImplemented("llRemoteLoadScript"); } 953 public void llRemoteLoadScript() { NotImplemented("llRemoteLoadScript"); }
928 public void llSetRemoteScriptAccessPin(int pin) { NotImplemented("llSetRemoteScriptAccessPin"); } 954 public void llSetRemoteScriptAccessPin(int pin) { NotImplemented("llSetRemoteScriptAccessPin"); }
929 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) { NotImplemented("llRemoteLoadScriptPin"); } 955 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) { NotImplemented("llRemoteLoadScriptPin"); }
930 public void llOpenRemoteDataChannel() { NotImplemented("llOpenRemoteDataChannel"); } 956
957 // remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval)
958 // Not sure where these constants should live:
959 // REMOTE_DATA_CHANNEL = 1
960 // REMOTE_DATA_REQUEST = 2
961 // REMOTE_DATA_REPLY = 3
962 public void llOpenRemoteDataChannel() {
963
964 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
965 LLUUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID);
966 object[] resobj = new object[] { 1, channelID.ToString(), LLUUID.Zero.ToString(), "", 0, "" };
967 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(m_localID, m_itemID, "remote_data", resobj);
968
969 }
970
931 public string llSendRemoteData(string channel, string dest, int idata, string sdata) { NotImplemented("llSendRemoteData"); return ""; } 971 public string llSendRemoteData(string channel, string dest, int idata, string sdata) { NotImplemented("llSendRemoteData"); return ""; }
932 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) { NotImplemented("llRemoteDataReply"); } 972
933 public void llCloseRemoteDataChannel(string channel) { NotImplemented("llCloseRemoteDataChannel"); } 973 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
974 {
975
976 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
977 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
978
979 }
980
981 public void llCloseRemoteDataChannel(string channel) {
982
983 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
984 xmlrpcMod.CloseXMLRPCChannel(channel);
985
986 }
934 987
935 public string llMD5String(string src, int nonce) 988 public string llMD5String(string src, int nonce)
936 { 989 {
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs
index 8ab0c30..5b92ff0 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/LSLLongCmdHandler.cs
@@ -4,6 +4,8 @@ using System.Text;
4using System.Threading; 4using System.Threading;
5using libsecondlife; 5using libsecondlife;
6using OpenSim.Region.ScriptEngine.Common; 6using OpenSim.Region.ScriptEngine.Common;
7using OpenSim.Region.Environment.Modules;
8using OpenSim.Region.Environment.Interfaces;
7 9
8namespace OpenSim.Region.ScriptEngine.DotNetEngine 10namespace OpenSim.Region.ScriptEngine.DotNetEngine
9{ 11{
@@ -26,6 +28,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
26 cmdHandlerThread.Priority = ThreadPriority.BelowNormal; 28 cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
27 cmdHandlerThread.IsBackground = true; 29 cmdHandlerThread.IsBackground = true;
28 cmdHandlerThread.Start(); 30 cmdHandlerThread.Start();
31
29 } 32 }
30 ~LSLLongCmdHandler() 33 ~LSLLongCmdHandler()
31 { 34 {
@@ -50,11 +53,19 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
50 { 53 {
51 // Check timers 54 // Check timers
52 CheckTimerEvents(); 55 CheckTimerEvents();
56 Thread.Sleep(25);
53 // Check HttpRequests 57 // Check HttpRequests
54 CheckHttpRequests(); 58 CheckHttpRequests();
59 Thread.Sleep(25);
60 // Check XMLRPCRequests
61 CheckXMLRPCRequests();
62 Thread.Sleep(25);
63 // Check Listeners
64 CheckListeners();
65 Thread.Sleep(25);
55 66
56 // Sleep before next cycle 67 // Sleep before next cycle
57 Thread.Sleep(cmdHandlerThreadCycleSleepms); 68 //Thread.Sleep(cmdHandlerThreadCycleSleepms);
58 } 69 }
59 } 70 }
60 71
@@ -258,5 +269,53 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
258 } 269 }
259 #endregion 270 #endregion
260 271
272 public void CheckXMLRPCRequests()
273 {
274
275 IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
276
277 while (xmlrpc.hasRequests())
278 {
279 RPCRequestInfo rInfo = xmlrpc.GetNextRequest();
280 System.Console.WriteLine("PICKED REQUEST");
281
282 //Deliver data to prim's remote_data handler
283 object[] resobj = new object[] {
284 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), "", rInfo.GetIntValue(), rInfo.GetStrVal()
285 };
286 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
287 rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", resobj
288 );
289
290 }
291
292 }
293
294 public void CheckListeners()
295 {
296
297 IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
298
299 while (comms.HasMessages())
300 {
301 ListenerInfo lInfo = comms.GetNextMessage();
302 System.Console.WriteLine("PICKED LISTENER");
303
304 //Deliver data to prim's listen handler
305 object[] resobj = new object[] {
306 lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage()
307 };
308
309 m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
310 lInfo.GetLocalID(), lInfo.GetItemID(), "listen", resobj
311 );
312
313 }
314
315 }
316
317
318
319
261 } 320 }
262} 321}
diff --git a/prebuild.xml b/prebuild.xml
index 543f475..a551f1b 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -474,6 +474,7 @@
474 <Reference name="OpenSim.Framework.Console"/> 474 <Reference name="OpenSim.Framework.Console"/>
475 <Reference name="OpenSim.Region.Physics.Manager"/> 475 <Reference name="OpenSim.Region.Physics.Manager"/>
476 <Reference name="OpenSim.Framework.Servers"/> 476 <Reference name="OpenSim.Framework.Servers"/>
477 <Reference name="OpenSim.Region.ScriptEngine.DotNetEngine"/>
477 <!-- For scripting in funny languages by default --> 478 <!-- For scripting in funny languages by default -->
478 <Reference name="Microsoft.JScript"/> 479 <Reference name="Microsoft.JScript"/>
479 <Reference name="XMLRPC.dll"/> 480 <Reference name="XMLRPC.dll"/>