aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/XMLRPCModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/XMLRPCModule.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/XMLRPCModule.cs680
1 files changed, 0 insertions, 680 deletions
diff --git a/OpenSim/Region/Environment/Modules/XMLRPCModule.cs b/OpenSim/Region/Environment/Modules/XMLRPCModule.cs
deleted file mode 100644
index e915fb8..0000000
--- a/OpenSim/Region/Environment/Modules/XMLRPCModule.cs
+++ /dev/null
@@ -1,680 +0,0 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33using System.Threading;
34using libsecondlife;
35using log4net;
36using Nini.Config;
37using Nwc.XmlRpc;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers;
40using OpenSim.Region.Environment.Interfaces;
41using OpenSim.Region.Environment.Scenes;
42
43/*****************************************************
44 *
45 * XMLRPCModule
46 *
47 * Module for accepting incoming communications from
48 * external XMLRPC client and calling a remote data
49 * procedure for a registered data channel/prim.
50 *
51 *
52 * 1. On module load, open a listener port
53 * 2. Attach an XMLRPC handler
54 * 3. When a request is received:
55 * 3.1 Parse into components: channel key, int, string
56 * 3.2 Look up registered channel listeners
57 * 3.3 Call the channel (prim) remote data method
58 * 3.4 Capture the response (llRemoteDataReply)
59 * 3.5 Return response to client caller
60 * 3.6 If no response from llRemoteDataReply within
61 * RemoteReplyScriptTimeout, generate script timeout fault
62 *
63 * Prims in script must:
64 * 1. Open a remote data channel
65 * 1.1 Generate a channel ID
66 * 1.2 Register primid,channelid pair with module
67 * 2. Implement the remote data procedure handler
68 *
69 * llOpenRemoteDataChannel
70 * llRemoteDataReply
71 * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval)
72 * llCloseRemoteDataChannel
73 *
74 * **************************************************/
75
76namespace OpenSim.Region.Environment.Modules
77{
78 public class XMLRPCModule : IRegionModule, IXMLRPC
79 {
80 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
81
82 private object XMLRPCListLock = new object();
83 private string m_name = "XMLRPCModule";
84 private int RemoteReplyScriptWait = 300;
85 private int RemoteReplyScriptTimeout = 9000;
86 private int m_remoteDataPort = 0;
87 private List<Scene> m_scenes = new List<Scene>();
88
89 // <channel id, RPCChannelInfo>
90 private Dictionary<LLUUID, RPCChannelInfo> m_openChannels;
91
92 private Dictionary<LLUUID, RPCRequestInfo> m_rpcPending;
93 private Dictionary<LLUUID, RPCRequestInfo> m_rpcPendingResponses;
94
95 private Dictionary<LLUUID, SendRemoteDataRequest> m_pendingSRDResponses;
96
97 public void Initialise(Scene scene, IConfigSource config)
98 {
99 try
100 {
101 m_remoteDataPort = config.Configs["Network"].GetInt("remoteDataPort", m_remoteDataPort);
102 }
103 catch (Exception)
104 {
105 }
106
107 if (!m_scenes.Contains(scene))
108 {
109 m_scenes.Add(scene);
110
111 scene.RegisterModuleInterface<IXMLRPC>(this);
112 }
113 }
114
115 public void PostInitialise()
116 {
117 if (IsEnabled())
118 {
119 m_openChannels = new Dictionary<LLUUID, RPCChannelInfo>();
120 m_rpcPending = new Dictionary<LLUUID, RPCRequestInfo>();
121 m_rpcPendingResponses = new Dictionary<LLUUID, RPCRequestInfo>();
122 m_pendingSRDResponses = new Dictionary<LLUUID, SendRemoteDataRequest>();
123
124 // Start http server
125 // Attach xmlrpc handlers
126 m_log.Info("[REMOTE_DATA]: " +
127 "Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands.");
128 BaseHttpServer httpServer = new BaseHttpServer((uint)m_remoteDataPort);
129 httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData);
130 httpServer.Start();
131 }
132 }
133
134 public void Close()
135 {
136 }
137
138 public string Name
139 {
140 get { return m_name; }
141 }
142
143 public bool IsSharedModule
144 {
145 get { return true; }
146 }
147
148 public bool IsEnabled()
149 {
150 return (m_remoteDataPort > 0);
151 }
152
153 /**********************************************
154 * OpenXMLRPCChannel
155 *
156 * Generate a LLUUID channel key and add it and
157 * the prim id to dictionary <channelUUID, primUUID>
158 *
159 * First check if there is a channel assigned for
160 * this itemID. If there is, then someone called
161 * llOpenRemoteDataChannel twice. Just return the
162 * original channel. Other option is to delete the
163 * current channel and assign a new one.
164 *
165 * ********************************************/
166
167 public LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID)
168 {
169 LLUUID channel = new LLUUID();
170
171 //Is a dupe?
172 foreach (RPCChannelInfo ci in m_openChannels.Values)
173 {
174 if (ci.GetItemID().Equals(itemID))
175 {
176 // return the original channel ID for this item
177 channel = ci.GetChannelID();
178 break;
179 }
180 }
181
182 if (channel == LLUUID.Zero)
183 {
184 channel = LLUUID.Random();
185 RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, channel);
186 lock (XMLRPCListLock)
187 {
188 m_openChannels.Add(channel, rpcChanInfo);
189 }
190 }
191
192 return channel;
193 }
194
195 // Delete channels based on itemID
196 // for when a script is deleted
197 public void DeleteChannels(LLUUID itemID)
198 {
199
200 if (m_openChannels != null)
201 {
202 ArrayList tmp = new ArrayList();
203
204 lock (XMLRPCListLock)
205 {
206 foreach (RPCChannelInfo li in m_openChannels.Values)
207 {
208 if (li.GetItemID().Equals(itemID))
209 {
210 tmp.Add(itemID);
211 }
212 }
213
214 IEnumerator tmpEnumerator = tmp.GetEnumerator();
215 while ( tmpEnumerator.MoveNext() )
216 m_openChannels.Remove((LLUUID)tmpEnumerator.Current);
217 }
218
219 }
220
221 }
222
223 /**********************************************
224 * Remote Data Reply
225 *
226 * Response to RPC message
227 *
228 *********************************************/
229
230 public void RemoteDataReply(string channel, string message_id, string sdata, int idata)
231 {
232 RPCRequestInfo rpcInfo;
233 LLUUID message_key = new LLUUID(message_id);
234
235 if (m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo))
236 {
237 rpcInfo.SetStrRetval(sdata);
238 rpcInfo.SetIntRetval(idata);
239 rpcInfo.SetProcessed(true);
240 m_rpcPendingResponses.Remove(message_key);
241 }
242 }
243
244 /**********************************************
245 * CloseXMLRPCChannel
246 *
247 * Remove channel from dictionary
248 *
249 *********************************************/
250
251 public void CloseXMLRPCChannel(LLUUID channelKey)
252 {
253 if (m_openChannels.ContainsKey(channelKey))
254 m_openChannels.Remove(channelKey);
255 }
256
257
258 public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request)
259 {
260 XmlRpcResponse response = new XmlRpcResponse();
261
262 Hashtable requestData = (Hashtable)request.Params[0];
263 bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") &&
264 requestData.Contains("StringValue"));
265
266 if (GoodXML)
267 {
268 LLUUID channel = new LLUUID((string)requestData["Channel"]);
269 RPCChannelInfo rpcChanInfo;
270 if (m_openChannels.TryGetValue(channel, out rpcChanInfo))
271 {
272 string intVal = (string)requestData["IntValue"];
273 string strVal = (string)requestData["StringValue"];
274
275 RPCRequestInfo rpcInfo;
276
277 lock (XMLRPCListLock)
278 {
279 rpcInfo =
280 new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal,
281 intVal);
282 m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo);
283 }
284
285 int timeoutCtr = 0;
286
287 while (!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout))
288 {
289 Thread.Sleep(RemoteReplyScriptWait);
290 timeoutCtr += RemoteReplyScriptWait;
291 }
292 if (rpcInfo.IsProcessed())
293 {
294 Hashtable param = new Hashtable();
295 param["StringValue"] = rpcInfo.GetStrRetval();
296 param["IntValue"] = Convert.ToString(rpcInfo.GetIntRetval());
297
298 ArrayList parameters = new ArrayList();
299 parameters.Add(param);
300
301 response.Value = parameters;
302 rpcInfo = null;
303 }
304 else
305 {
306 response.SetFault(-1, "Script timeout");
307 rpcInfo = null;
308 }
309 }
310 else
311 {
312 response.SetFault(-1, "Invalid channel");
313 }
314 }
315
316 return response;
317 }
318
319 public bool hasRequests()
320 {
321 lock (XMLRPCListLock)
322 {
323 if (m_rpcPending != null)
324 return (m_rpcPending.Count > 0);
325 else
326 return false;
327 }
328 }
329
330 public RPCRequestInfo GetNextCompletedRequest()
331 {
332 if (m_rpcPending != null)
333 {
334 lock (XMLRPCListLock)
335 {
336 foreach (LLUUID luid in m_rpcPending.Keys)
337 {
338 RPCRequestInfo tmpReq;
339
340 if (m_rpcPending.TryGetValue(luid, out tmpReq))
341 {
342
343 if (!tmpReq.IsProcessed()) return tmpReq;
344 }
345 }
346 }
347 }
348 return null;
349 }
350
351 public void RemoveCompletedRequest(LLUUID id)
352 {
353 lock (XMLRPCListLock)
354 {
355 RPCRequestInfo tmp;
356 if (m_rpcPending.TryGetValue(id, out tmp))
357 {
358 m_rpcPending.Remove(id);
359 m_rpcPendingResponses.Add(id, tmp);
360 }
361 else
362 {
363 Console.WriteLine("UNABLE TO REMOVE COMPLETED REQUEST");
364 }
365 }
366 }
367
368 public LLUUID SendRemoteData(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata)
369 {
370
371 SendRemoteDataRequest req = new SendRemoteDataRequest(
372 localID, itemID, channel, dest, idata, sdata
373 );
374 m_pendingSRDResponses.Add(req.GetReqID(), req);
375 return req.process();
376
377 }
378
379 public SendRemoteDataRequest GetNextCompletedSRDRequest()
380 {
381 if (m_pendingSRDResponses != null)
382 {
383 lock (XMLRPCListLock)
384 {
385 foreach (LLUUID luid in m_pendingSRDResponses.Keys)
386 {
387 SendRemoteDataRequest tmpReq;
388
389 if (m_pendingSRDResponses.TryGetValue(luid, out tmpReq))
390 {
391 if (tmpReq.finished)
392 return tmpReq;
393 }
394 }
395 }
396 }
397 return null;
398 }
399
400 public void RemoveCompletedSRDRequest(LLUUID id)
401 {
402 lock (XMLRPCListLock)
403 {
404 SendRemoteDataRequest tmpReq;
405 if (m_pendingSRDResponses.TryGetValue(id, out tmpReq))
406 {
407 m_pendingSRDResponses.Remove(id);
408 }
409 }
410 }
411
412 public void CancelSRDRequests(LLUUID itemID)
413 {
414 if (m_pendingSRDResponses != null)
415 {
416 lock (XMLRPCListLock)
417 {
418 foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values)
419 {
420 if (li.m_itemID.Equals(itemID))
421 m_pendingSRDResponses.Remove(li.GetReqID());
422 }
423 }
424 }
425 }
426 }
427
428 /**************************************************************
429 *
430 * Class RPCRequestInfo
431 *
432 * Holds details about incoming requests until they are picked
433 * from the queue by LSLLongCmdHandler
434 * ***********************************************************/
435
436 public class RPCRequestInfo
437 {
438 private string m_StrVal;
439 private string m_IntVal;
440 private bool m_processed;
441 private string m_respStr;
442 private int m_respInt;
443 private uint m_localID;
444 private LLUUID m_ItemID;
445 private LLUUID m_MessageID;
446 private LLUUID m_ChannelKey;
447
448 public RPCRequestInfo(uint localID, LLUUID itemID, LLUUID channelKey, string strVal, string intVal)
449 {
450 m_localID = localID;
451 m_StrVal = strVal;
452 m_IntVal = intVal;
453 m_ItemID = itemID;
454 m_ChannelKey = channelKey;
455 m_MessageID = LLUUID.Random();
456 m_processed = false;
457 m_respStr = String.Empty;
458 m_respInt = 0;
459 }
460
461 public bool IsProcessed()
462 {
463 return m_processed;
464 }
465
466 public LLUUID GetChannelKey()
467 {
468 return m_ChannelKey;
469 }
470
471 public void SetProcessed(bool processed)
472 {
473 m_processed = processed;
474 }
475
476 public void SetStrRetval(string resp)
477 {
478 m_respStr = resp;
479 }
480
481 public string GetStrRetval()
482 {
483 return m_respStr;
484 }
485 public void SetIntRetval(int resp)
486 {
487 m_respInt = resp;
488 }
489
490 public int GetIntRetval()
491 {
492 return m_respInt;
493 }
494 public uint GetLocalID()
495 {
496 return m_localID;
497 }
498
499 public LLUUID GetItemID()
500 {
501 return m_ItemID;
502 }
503
504 public string GetStrVal()
505 {
506 return m_StrVal;
507 }
508
509 public int GetIntValue()
510 {
511 return int.Parse(m_IntVal);
512 }
513
514 public LLUUID GetMessageID()
515 {
516 return m_MessageID;
517 }
518 }
519
520 public class RPCChannelInfo
521 {
522 private LLUUID m_itemID;
523 private uint m_localID;
524 private LLUUID m_ChannelKey;
525
526 public RPCChannelInfo(uint localID, LLUUID itemID, LLUUID channelID)
527 {
528 m_ChannelKey = channelID;
529 m_localID = localID;
530 m_itemID = itemID;
531 }
532
533 public LLUUID GetItemID()
534 {
535 return m_itemID;
536 }
537
538 public LLUUID GetChannelID()
539 {
540 return m_ChannelKey;
541 }
542
543 public uint GetLocalID()
544 {
545 return m_localID;
546 }
547
548 }
549
550 public class SendRemoteDataRequest
551 {
552
553 public LLUUID reqID;
554 public string destURL;
555 public string channel;
556 public string sdata;
557 public int idata;
558 public bool finished;
559 public string response_sdata;
560 public int response_idata;
561 public XmlRpcRequest request;
562 private Thread httpThread;
563 public LLUUID m_itemID;
564 public uint m_localID;
565 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
566
567 public SendRemoteDataRequest(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata)
568 {
569
570 this.channel = channel;
571 this.destURL = dest;
572 this.idata = idata;
573 this.sdata = sdata;
574 m_itemID = itemID;
575 m_localID = localID;
576
577 reqID = LLUUID.Random();
578
579 }
580
581 public LLUUID process()
582 {
583 httpThread = new Thread(SendRequest);
584 httpThread.Name = "HttpRequestThread";
585 httpThread.Priority = ThreadPriority.BelowNormal;
586 httpThread.IsBackground = true;
587 finished = false;
588 httpThread.Start();
589 ThreadTracker.Add(httpThread);
590
591 return reqID;
592
593 }
594
595 /*
596 * TODO: More work on the response codes. Right now
597 * returning 200 for success or 499 for exception
598 */
599
600 public void SendRequest()
601 {
602 Hashtable param = new Hashtable();
603
604 // Check if channel is an LLUUID
605 // if not, use as method name
606 LLUUID parseUID;
607 string mName = "llRemoteData";
608 if( (channel != null) && (channel != "") )
609 if( !LLUUID.TryParse(channel, out parseUID) )
610 mName = channel;
611 else
612 param["Channel"] = channel;
613
614 param["StringValue"] = sdata;
615 param["IntValue"] = Convert.ToString(idata);
616
617 ArrayList parameters = new ArrayList();
618 parameters.Add(param);
619 XmlRpcRequest req = new XmlRpcRequest(mName, parameters);
620 try
621 {
622 XmlRpcResponse resp = req.Send(destURL, 30000);
623 if (resp != null)
624 {
625 Hashtable respParms;
626 if(resp.Value.GetType().Equals(Type.GetType("System.Collections.Hashtable"))) {
627 respParms = (Hashtable)resp.Value;
628 }
629 else {
630 ArrayList respData = (ArrayList)resp.Value;
631 respParms = (Hashtable)respData[0];
632 }
633 if (respParms != null)
634 {
635 if (respParms.Contains("StringValue"))
636 {
637 sdata = (string)respParms["StringValue"];
638 }
639 if (respParms.Contains("IntValue"))
640 {
641 idata = Convert.ToInt32((string)respParms["IntValue"]);
642 }
643 if (respParms.Contains("faultString"))
644 {
645 sdata = (string)respParms["faultString"];
646 }
647 if (respParms.Contains("faultCode"))
648 {
649 idata = Convert.ToInt32(respParms["faultCode"]);
650 }
651 }
652 }
653 }
654 catch (WebException we)
655 {
656 sdata = we.Message;
657 m_log.Warn("[SendRemoteDataRequest]: Request failed");
658 m_log.Warn(we.StackTrace);
659 }
660
661 finished = true;
662 }
663
664 public void Stop()
665 {
666 try
667 {
668 httpThread.Abort();
669 }
670 catch (Exception)
671 {
672 }
673 }
674
675 public LLUUID GetReqID()
676 {
677 return reqID;
678 }
679 }
680}