aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/XMLRPCModule.cs
diff options
context:
space:
mode:
authorAdam Frisby2008-04-30 21:16:36 +0000
committerAdam Frisby2008-04-30 21:16:36 +0000
commitf5c312bc3c2567449c7268a54a08a54119f58d53 (patch)
tree424668a4bbec6873ebc5b8256f3671db102f5e9c /OpenSim/Region/Environment/Modules/XMLRPCModule.cs
parent* Adds the AuthbuyerID field to sqlite and makes use of it. (diff)
downloadopensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.zip
opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.gz
opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.bz2
opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.xz
* Refactored Environment/Modules directory - modules now reside in their own directory with any associated module-specific classes.
* Each module directory is currently inside one of the following category folders: Agent (Anything relating to do with Client<->Server communications.), Avatar (Anything to do with the avatar or presence inworld), Framework (Classes modules can use), Grid (Grid traffic, new OGS2 grid comms), Scripting (Scripting functions, etc), World (The enrivonment/scene, IE Sun/Tree modules.) * This should be moved into a seperate project file.
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}