OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
HGMessageTransferModule.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 
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Net;
32 using System.Reflection;
33 using log4net;
34 using Nini.Config;
35 using Nwc.XmlRpc;
36 using Mono.Addins;
37 using OpenMetaverse;
38 using OpenSim.Framework;
39 using OpenSim.Framework.Servers;
40 using OpenSim.Region.Framework.Interfaces;
41 using OpenSim.Region.Framework.Scenes;
44 using OpenSim.Services.Interfaces;
45 using OpenSim.Services.Connectors.InstantMessage;
46 using OpenSim.Services.Connectors.Hypergrid;
47 using OpenSim.Server.Handlers.Hypergrid;
48 
49 namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
50 {
51  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGMessageTransferModule")]
53  {
54  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 
56  protected bool m_Enabled = false;
57  protected List<Scene> m_Scenes = new List<Scene>();
58 
60  protected Dictionary<UUID, object> m_UserLocationMap = new Dictionary<UUID, object>();
61 
63 
64  IUserManagement m_uMan;
65  IUserManagement UserManagementModule
66  {
67  get
68  {
69  if (m_uMan == null)
70  m_uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
71  return m_uMan;
72  }
73  }
74 
75  public virtual void Initialise(IConfigSource config)
76  {
77  IConfig cnf = config.Configs["Messaging"];
78  if (cnf != null && cnf.GetString(
79  "MessageTransferModule", "MessageTransferModule") != Name)
80  {
81  m_log.Debug("[HG MESSAGE TRANSFER]: Disabled by configuration");
82  return;
83  }
84 
86  m_IMService = imServer.GetService();
87  m_Enabled = true;
88  }
89 
90  public virtual void AddRegion(Scene scene)
91  {
92  if (!m_Enabled)
93  return;
94 
95  lock (m_Scenes)
96  {
97  m_log.DebugFormat("[HG MESSAGE TRANSFER]: Message transfer module {0} active", Name);
98  scene.RegisterModuleInterface<IMessageTransferModule>(this);
99  m_Scenes.Add(scene);
100  }
101  }
102 
103  public virtual void PostInitialise()
104  {
105  if (!m_Enabled)
106  return;
107 
108  }
109 
110  public virtual void RegionLoaded(Scene scene)
111  {
112  }
113 
114  public virtual void RemoveRegion(Scene scene)
115  {
116  if (!m_Enabled)
117  return;
118 
119  lock (m_Scenes)
120  {
121  m_Scenes.Remove(scene);
122  }
123  }
124 
125  public virtual void Close()
126  {
127  }
128 
129  public virtual string Name
130  {
131  get { return "HGMessageTransferModule"; }
132  }
133 
134  public virtual Type ReplaceableInterface
135  {
136  get { return null; }
137  }
138 
140  {
141  UUID toAgentID = new UUID(im.toAgentID);
142 
143  // Try root avatar only first
144  foreach (Scene scene in m_Scenes)
145  {
146 // m_log.DebugFormat(
147 // "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}",
148 // toAgentID.ToString(), scene.RegionInfo.RegionName);
149  ScenePresence sp = scene.GetScenePresence(toAgentID);
150  if (sp != null && !sp.IsChildAgent)
151  {
152  // Local message
153 // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
154  sp.ControllingClient.SendInstantMessage(im);
155 
156  // Message sent
157  result(true);
158  return;
159  }
160  }
161 
162  // try child avatar second
163  foreach (Scene scene in m_Scenes)
164  {
165 // m_log.DebugFormat(
166 // "[HG INSTANT MESSAGE]: Looking for child of {0} in {1}",
167 // toAgentID, scene.RegionInfo.RegionName);
168  ScenePresence sp = scene.GetScenePresence(toAgentID);
169  if (sp != null)
170  {
171  // Local message
172 // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
173  sp.ControllingClient.SendInstantMessage(im);
174 
175  // Message sent
176  result(true);
177  return;
178  }
179  }
180 
181 // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
182  // Is the user a local user?
183  string url = string.Empty;
184  bool foreigner = false;
185  if (UserManagementModule != null && !UserManagementModule.IsLocalGridUser(toAgentID)) // foreign user
186  {
187  url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI");
188  foreigner = true;
189  }
190 
191  Util.FireAndForget(delegate
192  {
193  bool success = false;
194  if (foreigner && url == string.Empty) // we don't know about this user
195  {
196  string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID);
197  m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI);
198  if (recipientUUI != string.Empty)
199  {
200  UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty;
201  if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret))
202  {
203  success = m_IMService.OutgoingInstantMessage(im, u, true);
204  if (success)
205  UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last);
206  }
207  }
208  }
209  else
210  success = m_IMService.OutgoingInstantMessage(im, url, foreigner);
211 
212  if (!success && !foreigner)
213  HandleUndeliverableMessage(im, result);
214  else
215  result(success);
216  }, null, "HGMessageTransferModule.SendInstantMessage");
217 
218  return;
219  }
220 
221  protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID)
222  {
223  bool successful = false;
224  foreach (Scene scene in m_Scenes)
225  {
226  ScenePresence sp = scene.GetScenePresence(toAgentID);
227  if(sp != null && !sp.IsChildAgent)
228  {
229  scene.EventManager.TriggerIncomingInstantMessage(gim);
230  successful = true;
231  }
232  }
233 
234  if (!successful)
235  {
236  // If the message can't be delivered to an agent, it
237  // is likely to be a group IM. On a group IM, the
238  // imSessionID = toAgentID = group id. Raise the
239  // unhandled IM event to give the groups module
240  // a chance to pick it up. We raise that in a random
241  // scene, since the groups module is shared.
242  //
243  m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim);
244  }
245 
246  return successful;
247  }
248 
250  {
251  UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
252 
253  // If this event has handlers, then an IM from an agent will be
254  // considered delivered. This will suppress the error message.
255  //
256  if (handlerUndeliveredMessage != null)
257  {
258  handlerUndeliveredMessage(im);
259  if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
260  result(true);
261  else
262  result(false);
263  return;
264  }
265 
266  //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable");
267  result(false);
268  }
269 
270  private string TryGetRecipientUUI(UUID fromAgent, UUID toAgent)
271  {
272  // Let's call back the fromAgent's user agent service
273  // Maybe that service knows about the toAgent
274  IClientAPI client = LocateClientObject(fromAgent);
275  if (client != null)
276  {
277  AgentCircuitData circuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.AgentId);
278  if (circuit != null)
279  {
280  if (circuit.ServiceURLs.ContainsKey("HomeURI"))
281  {
282  string uasURL = circuit.ServiceURLs["HomeURI"].ToString();
283  m_log.DebugFormat("[HG MESSAGE TRANSFER]: getting UUI of user {0} from {1}", toAgent, uasURL);
285 
286  string agentUUI = string.Empty;
287  try
288  {
289  agentUUI = uasConn.GetUUI(fromAgent, toAgent);
290  }
291  catch (Exception e) {
292  m_log.Debug("[HG MESSAGE TRANSFER]: GetUUI call failed ", e);
293  }
294 
295  return agentUUI;
296  }
297  }
298  }
299 
300  return string.Empty;
301  }
302 
306  public IClientAPI LocateClientObject(UUID agentID)
307  {
308  lock (m_Scenes)
309  {
310  foreach (Scene scene in m_Scenes)
311  {
312  ScenePresence presence = scene.GetScenePresence(agentID);
313  if (presence != null && !presence.IsChildAgent)
314  return presence.ControllingClient;
315  }
316  }
317 
318  return null;
319  }
320 
321  #region IInstantMessageSimConnector
323  {
324  //m_log.DebugFormat("[XXX] Hook SendInstantMessage {0}", im.message);
325  UUID agentID = new UUID(im.toAgentID);
326  return SendIMToScene(im, agentID);
327  }
328  #endregion
329 
330 
331  }
332 }
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...
delegate void UndeliveredMessage(GridInstantMessage im)
OpenSim.Services.Interfaces.PresenceInfo PresenceInfo
void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result)
Appropriately handle a known undeliverable message without attempting a send.
delegate void MessageResultNotification(bool success)
Dictionary< string, object > ServiceURLs
OpenSim.Services.Interfaces.GridRegion GridRegion
virtual void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
virtual void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...
void SendInstantMessage(GridInstantMessage im, MessageResultNotification result)
Attempt to send an instant message to a given destination.
IClientAPI LocateClientObject(UUID agentID)
Find the root client for a ID
Circuit data for an agent. Connection information shared between regions that accept UDP connections ...
Interactive OpenSim region server
Definition: OpenSim.cs:55
static BaseHttpServer Instance
Set the main HTTP server instance.
Definition: MainServer.cs:83
virtual void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
virtual void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
This maintains the relationship between a UUID and a user name.