OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
MessageTransferModule.cs
Go to the documentation of this file.
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 OpenSimulator 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 using System;
28 using System.Collections;
29 using System.Collections.Generic;
30 using System.Net;
31 using System.Reflection;
32 using log4net;
33 using Mono.Addins;
34 using Nini.Config;
35 using Nwc.XmlRpc;
36 using OpenMetaverse;
37 using OpenSim.Framework;
38 using OpenSim.Framework.Servers;
39 using OpenSim.Region.Framework.Interfaces;
40 using OpenSim.Region.Framework.Scenes;
43 using OpenSim.Services.Interfaces;
44 
45 namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
46 {
47  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MessageTransferModule")]
49  {
50  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 
52  private bool m_Enabled = false;
53  protected string m_MessageKey = String.Empty;
54  protected List<Scene> m_Scenes = new List<Scene>();
55  protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>();
56 
58 
59  private IPresenceService m_PresenceService;
60  protected IPresenceService PresenceService
61  {
62  get
63  {
64  if (m_PresenceService == null)
65  m_PresenceService = m_Scenes[0].RequestModuleInterface<IPresenceService>();
66  return m_PresenceService;
67  }
68  }
69 
70  public virtual void Initialise(IConfigSource config)
71  {
72  IConfig cnf = config.Configs["Messaging"];
73  if (cnf != null)
74  {
75  if (cnf.GetString("MessageTransferModule",
76  "MessageTransferModule") != "MessageTransferModule")
77  {
78  return;
79  }
80 
81  m_MessageKey = cnf.GetString("MessageKey", String.Empty);
82  }
83  m_log.Debug("[MESSAGE TRANSFER]: Module enabled");
84  m_Enabled = true;
85  }
86 
87  public virtual void AddRegion(Scene scene)
88  {
89  if (!m_Enabled)
90  return;
91 
92  lock (m_Scenes)
93  {
94  m_log.Debug("[MESSAGE TRANSFER]: Message transfer module active");
95  scene.RegisterModuleInterface<IMessageTransferModule>(this);
96  m_Scenes.Add(scene);
97  }
98  }
99 
100  public virtual void PostInitialise()
101  {
102  if (!m_Enabled)
103  return;
104 
105  MainServer.Instance.AddXmlRPCHandler(
106  "grid_instant_message", processXMLRPCGridInstantMessage);
107  }
108 
109  public virtual void RegionLoaded(Scene scene)
110  {
111  }
112 
113  public virtual void RemoveRegion(Scene scene)
114  {
115  if (!m_Enabled)
116  return;
117 
118  lock (m_Scenes)
119  {
120  m_Scenes.Remove(scene);
121  }
122  }
123 
124  public virtual void Close()
125  {
126  }
127 
128  public virtual string Name
129  {
130  get { return "MessageTransferModule"; }
131  }
132 
133  public virtual Type ReplaceableInterface
134  {
135  get { return null; }
136  }
137 
139  {
140  UUID toAgentID = new UUID(im.toAgentID);
141 
142  if (toAgentID == UUID.Zero)
143  return;
144 
145  // Try root avatar only first
146  foreach (Scene scene in m_Scenes)
147  {
148 // m_log.DebugFormat(
149 // "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
150 // toAgentID.ToString(), scene.RegionInfo.RegionName);
151 
152  ScenePresence sp = scene.GetScenePresence(toAgentID);
153  if (sp != null && !sp.IsChildAgent)
154  {
155  // Local message
156 // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
157 
158  sp.ControllingClient.SendInstantMessage(im);
159 
160  // Message sent
161  result(true);
162  return;
163  }
164  }
165 
166  // try child avatar second
167  foreach (Scene scene in m_Scenes)
168  {
169 // m_log.DebugFormat(
170 // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
171 
172  ScenePresence sp = scene.GetScenePresence(toAgentID);
173  if (sp != null)
174  {
175  // Local message
176 // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
177 
178  sp.ControllingClient.SendInstantMessage(im);
179 
180  // Message sent
181  result(true);
182  return;
183  }
184  }
185 
186 // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
187 
188  SendGridInstantMessageViaXMLRPC(im, result);
189  }
190 
192  {
193  UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
194 
195  // If this event has handlers, then an IM from an agent will be
196  // considered delivered. This will suppress the error message.
197  //
198  if (handlerUndeliveredMessage != null)
199  {
200  handlerUndeliveredMessage(im);
201  if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
202  result(true);
203  else
204  result(false);
205  return;
206  }
207 
208  //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable");
209  result(false);
210  }
211 
218  protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient)
219  {
220  bool successful = false;
221 
222  // TODO: For now, as IMs seem to be a bit unreliable on OSGrid, catch all exception that
223  // happen here and aren't caught and log them.
224  try
225  {
226  // various rational defaults
227  UUID fromAgentID = UUID.Zero;
228  UUID toAgentID = UUID.Zero;
229  UUID imSessionID = UUID.Zero;
230  uint timestamp = 0;
231  string fromAgentName = "";
232  string message = "";
233  byte dialog = (byte)0;
234  bool fromGroup = false;
235  byte offline = (byte)0;
236  uint ParentEstateID=0;
237  Vector3 Position = Vector3.Zero;
238  UUID RegionID = UUID.Zero ;
239  byte[] binaryBucket = new byte[0];
240 
241  float pos_x = 0;
242  float pos_y = 0;
243  float pos_z = 0;
244  //m_log.Info("Processing IM");
245 
246 
247  Hashtable requestData = (Hashtable)request.Params[0];
248  // Check if it's got all the data
249  if (requestData.ContainsKey("from_agent_id")
250  && requestData.ContainsKey("to_agent_id") && requestData.ContainsKey("im_session_id")
251  && requestData.ContainsKey("timestamp") && requestData.ContainsKey("from_agent_name")
252  && requestData.ContainsKey("message") && requestData.ContainsKey("dialog")
253  && requestData.ContainsKey("from_group")
254  && requestData.ContainsKey("offline") && requestData.ContainsKey("parent_estate_id")
255  && requestData.ContainsKey("position_x") && requestData.ContainsKey("position_y")
256  && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
257  && requestData.ContainsKey("binary_bucket"))
258  {
259  if (m_MessageKey != String.Empty)
260  {
261  XmlRpcResponse error_resp = new XmlRpcResponse();
262  Hashtable error_respdata = new Hashtable();
263  error_respdata["success"] = "FALSE";
264  error_resp.Value = error_respdata;
265 
266  if (!requestData.Contains("message_key"))
267  return error_resp;
268  if (m_MessageKey != (string)requestData["message_key"])
269  return error_resp;
270  }
271 
272  // Do the easy way of validating the UUIDs
273  UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
274  UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
275  UUID.TryParse((string)requestData["im_session_id"], out imSessionID);
276  UUID.TryParse((string)requestData["region_id"], out RegionID);
277 
278  try
279  {
280  timestamp = (uint)Convert.ToInt32((string)requestData["timestamp"]);
281  }
282  catch (ArgumentException)
283  {
284  }
285  catch (FormatException)
286  {
287  }
288  catch (OverflowException)
289  {
290  }
291 
292  fromAgentName = (string)requestData["from_agent_name"];
293  message = (string)requestData["message"];
294  if (message == null)
295  message = string.Empty;
296 
297  // Bytes don't transfer well over XMLRPC, so, we Base64 Encode them.
298  string requestData1 = (string)requestData["dialog"];
299  if (string.IsNullOrEmpty(requestData1))
300  {
301  dialog = 0;
302  }
303  else
304  {
305  byte[] dialogdata = Convert.FromBase64String(requestData1);
306  dialog = dialogdata[0];
307  }
308 
309  if ((string)requestData["from_group"] == "TRUE")
310  fromGroup = true;
311 
312  string requestData2 = (string)requestData["offline"];
313  if (String.IsNullOrEmpty(requestData2))
314  {
315  offline = 0;
316  }
317  else
318  {
319  byte[] offlinedata = Convert.FromBase64String(requestData2);
320  offline = offlinedata[0];
321  }
322 
323  try
324  {
325  ParentEstateID = (uint)Convert.ToInt32((string)requestData["parent_estate_id"]);
326  }
327  catch (ArgumentException)
328  {
329  }
330  catch (FormatException)
331  {
332  }
333  catch (OverflowException)
334  {
335  }
336 
337  try
338  {
339  pos_x = (uint)Convert.ToInt32((string)requestData["position_x"]);
340  }
341  catch (ArgumentException)
342  {
343  }
344  catch (FormatException)
345  {
346  }
347  catch (OverflowException)
348  {
349  }
350  try
351  {
352  pos_y = (uint)Convert.ToInt32((string)requestData["position_y"]);
353  }
354  catch (ArgumentException)
355  {
356  }
357  catch (FormatException)
358  {
359  }
360  catch (OverflowException)
361  {
362  }
363  try
364  {
365  pos_z = (uint)Convert.ToInt32((string)requestData["position_z"]);
366  }
367  catch (ArgumentException)
368  {
369  }
370  catch (FormatException)
371  {
372  }
373  catch (OverflowException)
374  {
375  }
376 
377  Position = new Vector3(pos_x, pos_y, pos_z);
378 
379  string requestData3 = (string)requestData["binary_bucket"];
380  if (string.IsNullOrEmpty(requestData3))
381  {
382  binaryBucket = new byte[0];
383  }
384  else
385  {
386  binaryBucket = Convert.FromBase64String(requestData3);
387  }
388 
389  // Create a New GridInstantMessageObject the the data
391  gim.fromAgentID = fromAgentID.Guid;
392  gim.fromAgentName = fromAgentName;
393  gim.fromGroup = fromGroup;
394  gim.imSessionID = imSessionID.Guid;
395  gim.RegionID = RegionID.Guid;
396  gim.timestamp = timestamp;
397  gim.toAgentID = toAgentID.Guid;
398  gim.message = message;
399  gim.dialog = dialog;
400  gim.offline = offline;
401  gim.ParentEstateID = ParentEstateID;
402  gim.Position = Position;
403  gim.binaryBucket = binaryBucket;
404 
405 
406  // Trigger the Instant message in the scene.
407  foreach (Scene scene in m_Scenes)
408  {
409  ScenePresence sp = scene.GetScenePresence(toAgentID);
410  if (sp != null && !sp.IsChildAgent)
411  {
412  scene.EventManager.TriggerIncomingInstantMessage(gim);
413  successful = true;
414  }
415  }
416  if (!successful)
417  {
418  // If the message can't be delivered to an agent, it
419  // is likely to be a group IM. On a group IM, the
420  // imSessionID = toAgentID = group id. Raise the
421  // unhandled IM event to give the groups module
422  // a chance to pick it up. We raise that in a random
423  // scene, since the groups module is shared.
424  //
425  m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim);
426  }
427  }
428  }
429  catch (Exception e)
430  {
431  m_log.Error("[INSTANT MESSAGE]: Caught unexpected exception:", e);
432  successful = false;
433  }
434 
435  //Send response back to region calling if it was successful
436  // calling region uses this to know when to look up a user's location again.
437  XmlRpcResponse resp = new XmlRpcResponse();
438  Hashtable respdata = new Hashtable();
439  if (successful)
440  respdata["success"] = "TRUE";
441  else
442  respdata["success"] = "FALSE";
443  resp.Value = respdata;
444 
445  return resp;
446  }
447 
448 
452  private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
453 
454  private class GIM {
455  public GridInstantMessage im;
456  public MessageResultNotification result;
457  };
458 
459  private Queue<GIM> pendingInstantMessages = new Queue<GIM>();
460  private int numInstantMessageThreads = 0;
461 
462  private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
463  {
464  lock (pendingInstantMessages) {
465  if (numInstantMessageThreads >= 4) {
466  GIM gim = new GIM();
467  gim.im = im;
468  gim.result = result;
469  pendingInstantMessages.Enqueue(gim);
470  } else {
471  ++ numInstantMessageThreads;
472  //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
473  GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
474  d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
475  }
476  }
477  }
478 
479 
480  private void GridInstantMessageCompleted(IAsyncResult iar)
481  {
482  GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
483  d.EndInvoke(iar);
484  }
485 
489 
494  private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
495  {
496  GIM gim;
497  do {
498  try {
499  SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
500  } catch (Exception e) {
501  m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
502  }
503  lock (pendingInstantMessages) {
504  if (pendingInstantMessages.Count > 0) {
505  gim = pendingInstantMessages.Dequeue();
506  im = gim.im;
507  result = gim.result;
508  } else {
509  gim = null;
510  -- numInstantMessageThreads;
511  //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
512  }
513  }
514  } while (gim != null);
515  }
516 
517  private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
518  {
519 
520  UUID toAgentID = new UUID(im.toAgentID);
521  PresenceInfo upd = null;
522  UUID regionID;
523  bool lookupAgent = false;
524 
525  lock (m_UserRegionMap)
526  {
527  if (m_UserRegionMap.ContainsKey(toAgentID))
528  {
529  upd = new PresenceInfo();
530  upd.RegionID = m_UserRegionMap[toAgentID];
531 
532  // We need to compare the current regionhandle with the previous region handle
533  // or the recursive loop will never end because it will never try to lookup the agent again
534  if (prevRegionID == upd.RegionID)
535  {
536  lookupAgent = true;
537  }
538  }
539  else
540  {
541  lookupAgent = true;
542  }
543  }
544 
545 
546  // Are we needing to look-up an agent?
547  if (lookupAgent)
548  {
549  // Non-cached user agent lookup.
550  PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
551  if (presences != null && presences.Length > 0)
552  {
553  foreach (PresenceInfo p in presences)
554  {
555  if (p.RegionID != UUID.Zero)
556  {
557  upd = p;
558  break;
559  }
560  }
561  }
562 
563  if (upd != null)
564  {
565  // check if we've tried this before..
566  // This is one way to end the recursive loop
567  //
568  if (upd.RegionID == prevRegionID)
569  {
570  // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
571  HandleUndeliverableMessage(im, result);
572  return;
573  }
574  }
575  else
576  {
577  // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
578  HandleUndeliverableMessage(im, result);
579  return;
580  }
581  }
582 
583  if (upd != null)
584  {
585  GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
586  upd.RegionID);
587  if (reginfo != null)
588  {
589  Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
590  // Not actually used anymore, left in for compatibility
591  // Remove at next interface change
592  //
593  msgdata["region_handle"] = 0;
594  bool imresult = doIMSending(reginfo, msgdata);
595  if (imresult)
596  {
597  // IM delivery successful, so store the Agent's location in our local cache.
598  lock (m_UserRegionMap)
599  {
600  if (m_UserRegionMap.ContainsKey(toAgentID))
601  {
602  m_UserRegionMap[toAgentID] = upd.RegionID;
603  }
604  else
605  {
606  m_UserRegionMap.Add(toAgentID, upd.RegionID);
607  }
608  }
609  result(true);
610  }
611  else
612  {
613  // try again, but lookup user this time.
614  // Warning, this must call the Async version
615  // of this method or we'll be making thousands of threads
616  // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
617  // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
618 
619  // This is recursive!!!!!
620  SendGridInstantMessageViaXMLRPCAsync(im, result,
621  upd.RegionID);
622  }
623  }
624  else
625  {
626  m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
627  HandleUndeliverableMessage(im, result);
628  }
629  }
630  else
631  {
632  HandleUndeliverableMessage(im, result);
633  }
634  }
635 
642  protected virtual bool doIMSending(GridRegion reginfo, Hashtable xmlrpcdata)
643  {
644  ArrayList SendParams = new ArrayList();
645  SendParams.Add(xmlrpcdata);
646  XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams);
647  try
648  {
649 
650  XmlRpcResponse GridResp = GridReq.Send(reginfo.ServerURI, 3000);
651 
652  Hashtable responseData = (Hashtable)GridResp.Value;
653 
654  if (responseData.ContainsKey("success"))
655  {
656  if ((string)responseData["success"] == "TRUE")
657  {
658  return true;
659  }
660  else
661  {
662  return false;
663  }
664  }
665  else
666  {
667  return false;
668  }
669  }
670  catch (WebException e)
671  {
672  m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond " + e.ToString(), reginfo.ServerURI.ToString());
673  }
674 
675  return false;
676  }
677 
684 // private virtual ulong getLocalRegionHandleFromUUID(UUID regionID)
685 // {
686 // ulong returnhandle = 0;
687 //
688 // lock (m_Scenes)
689 // {
690 // foreach (Scene sn in m_Scenes)
691 // {
692 // if (sn.RegionInfo.RegionID == regionID)
693 // {
694 // returnhandle = sn.RegionInfo.RegionHandle;
695 // break;
696 // }
697 // }
698 // }
699 // return returnhandle;
700 // }
701 
707  protected virtual Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg)
708  {
709  Hashtable gim = new Hashtable();
710  gim["from_agent_id"] = msg.fromAgentID.ToString();
711  // Kept for compatibility
712  gim["from_agent_session"] = UUID.Zero.ToString();
713  gim["to_agent_id"] = msg.toAgentID.ToString();
714  gim["im_session_id"] = msg.imSessionID.ToString();
715  gim["timestamp"] = msg.timestamp.ToString();
716  gim["from_agent_name"] = msg.fromAgentName;
717  gim["message"] = msg.message;
718  byte[] dialogdata = new byte[1];dialogdata[0] = msg.dialog;
719  gim["dialog"] = Convert.ToBase64String(dialogdata,Base64FormattingOptions.None);
720 
721  if (msg.fromGroup)
722  gim["from_group"] = "TRUE";
723  else
724  gim["from_group"] = "FALSE";
725  byte[] offlinedata = new byte[1]; offlinedata[0] = msg.offline;
726  gim["offline"] = Convert.ToBase64String(offlinedata, Base64FormattingOptions.None);
727  gim["parent_estate_id"] = msg.ParentEstateID.ToString();
728  gim["position_x"] = msg.Position.X.ToString();
729  gim["position_y"] = msg.Position.Y.ToString();
730  gim["position_z"] = msg.Position.Z.ToString();
731  gim["region_id"] = new UUID(msg.RegionID).ToString();
732  gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
733  if (m_MessageKey != String.Empty)
734  gim["message_key"] = m_MessageKey;
735  return gim;
736  }
737  }
738 }
virtual void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
virtual void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
virtual bool doIMSending(GridRegion reginfo, Hashtable xmlrpcdata)
This actually does the XMLRPC Request
virtual void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...
delegate void UndeliveredMessage(GridInstantMessage im)
virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result)
Attempt to send an instant message to a given destination.
delegate void MessageResultNotification(bool success)
OpenSim.Services.Interfaces.GridRegion GridRegion
virtual void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result)
Appropriately handle a known undeliverable message without attempting a send.
virtual void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
virtual Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg)
Get ulong region handle for region by it's Region UUID. We use region handles over grid comms because...
virtual void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
virtual void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
OpenSim.Services.Interfaces.PresenceInfo PresenceInfo
virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient)
Process a XMLRPC Grid Instant Message
string ServerURI
A well-formed URI for the host region server (namely "http://" + ExternalHostName) ...