aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/XMLRPCModule.cs
diff options
context:
space:
mode:
authorSean Dague2007-10-05 19:33:26 +0000
committerSean Dague2007-10-05 19:33:26 +0000
commit29aa41daa004531cc41649c1818e4e432600cc32 (patch)
tree6d2e3574b7222137a83fc6ba6502b197efb89bfc /OpenSim/Region/Environment/Modules/XMLRPCModule.cs
parentgetting all our line endings consistant again (diff)
downloadopensim-SC-29aa41daa004531cc41649c1818e4e432600cc32.zip
opensim-SC-29aa41daa004531cc41649c1818e4e432600cc32.tar.gz
opensim-SC-29aa41daa004531cc41649c1818e4e432600cc32.tar.bz2
opensim-SC-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
Diffstat (limited to 'OpenSim/Region/Environment/Modules/XMLRPCModule.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/XMLRPCModule.cs360
1 files changed, 360 insertions, 0 deletions
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}