28 using System.Collections;
29 using System.Collections.Generic;
31 using System.Reflection;
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;
45 namespace OpenSim.
Region.CoreModules.
Avatar.InstantMessage
47 [Extension(Path =
"/OpenSim/RegionModules", NodeName =
"RegionModule", Id =
"MessageTransferModule")]
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
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>();
64 if (m_PresenceService == null)
66 return m_PresenceService;
72 IConfig cnf = config.Configs[
"Messaging"];
75 if (cnf.GetString(
"MessageTransferModule",
76 "MessageTransferModule") !=
"MessageTransferModule")
81 m_MessageKey = cnf.GetString(
"MessageKey", String.Empty);
83 m_log.Debug(
"[MESSAGE TRANSFER]: Module enabled");
94 m_log.Debug(
"[MESSAGE TRANSFER]: Message transfer module active");
105 MainServer.Instance.AddXmlRPCHandler(
106 "grid_instant_message", processXMLRPCGridInstantMessage);
120 m_Scenes.Remove(scene);
128 public virtual string Name
130 get {
return "MessageTransferModule"; }
133 public virtual Type ReplaceableInterface
142 if (toAgentID ==
UUID.Zero)
146 foreach (
Scene scene
in m_Scenes)
158 sp.ControllingClient.SendInstantMessage(im);
167 foreach (
Scene scene
in m_Scenes)
178 sp.ControllingClient.SendInstantMessage(im);
188 SendGridInstantMessageViaXMLRPC(im, result);
198 if (handlerUndeliveredMessage != null)
200 handlerUndeliveredMessage(im);
201 if (im.
dialog == (byte)InstantMessageDialog.MessageFromAgent)
220 bool successful =
false;
227 UUID fromAgentID = UUID.Zero;
228 UUID toAgentID = UUID.Zero;
229 UUID imSessionID = UUID.Zero;
231 string fromAgentName =
"";
233 byte dialog = (byte)0;
234 bool fromGroup =
false;
235 byte offline = (byte)0;
236 uint ParentEstateID=0;
238 UUID RegionID = UUID.Zero ;
239 byte[] binaryBucket =
new byte[0];
247 Hashtable requestData = (Hashtable)request.Params[0];
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"))
259 if (m_MessageKey !=
String.Empty)
261 XmlRpcResponse error_resp =
new XmlRpcResponse();
262 Hashtable error_respdata =
new Hashtable();
263 error_respdata[
"success"] =
"FALSE";
264 error_resp.Value = error_respdata;
266 if (!requestData.Contains(
"message_key"))
268 if (m_MessageKey != (
string)requestData[
"message_key"])
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);
280 timestamp = (uint)Convert.ToInt32((
string)requestData[
"timestamp"]);
282 catch (ArgumentException)
285 catch (FormatException)
288 catch (OverflowException)
292 fromAgentName = (string)requestData[
"from_agent_name"];
293 message = (string)requestData[
"message"];
295 message = string.Empty;
298 string requestData1 = (string)requestData[
"dialog"];
299 if (
string.IsNullOrEmpty(requestData1))
305 byte[] dialogdata = Convert.FromBase64String(requestData1);
306 dialog = dialogdata[0];
309 if ((
string)requestData[
"from_group"] ==
"TRUE")
312 string requestData2 = (string)requestData[
"offline"];
313 if (
String.IsNullOrEmpty(requestData2))
319 byte[] offlinedata = Convert.FromBase64String(requestData2);
320 offline = offlinedata[0];
325 ParentEstateID = (uint)Convert.ToInt32((
string)requestData[
"parent_estate_id"]);
327 catch (ArgumentException)
330 catch (FormatException)
333 catch (OverflowException)
339 pos_x = (uint)Convert.ToInt32((
string)requestData[
"position_x"]);
341 catch (ArgumentException)
344 catch (FormatException)
347 catch (OverflowException)
352 pos_y = (uint)Convert.ToInt32((
string)requestData[
"position_y"]);
354 catch (ArgumentException)
357 catch (FormatException)
360 catch (OverflowException)
365 pos_z = (uint)Convert.ToInt32((
string)requestData[
"position_z"]);
367 catch (ArgumentException)
370 catch (FormatException)
373 catch (OverflowException)
377 Position =
new Vector3(pos_x, pos_y, pos_z);
379 string requestData3 = (string)requestData[
"binary_bucket"];
380 if (
string.IsNullOrEmpty(requestData3))
382 binaryBucket =
new byte[0];
386 binaryBucket = Convert.FromBase64String(requestData3);
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;
400 gim.offline = offline;
401 gim.ParentEstateID = ParentEstateID;
402 gim.Position = Position;
403 gim.binaryBucket = binaryBucket;
407 foreach (
Scene scene
in m_Scenes)
412 scene.EventManager.TriggerIncomingInstantMessage(gim);
425 m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim);
431 m_log.Error(
"[INSTANT MESSAGE]: Caught unexpected exception:", e);
437 XmlRpcResponse resp =
new XmlRpcResponse();
438 Hashtable respdata =
new Hashtable();
440 respdata[
"success"] =
"TRUE";
442 respdata[
"success"] =
"FALSE";
443 resp.Value = respdata;
459 private Queue<GIM> pendingInstantMessages =
new Queue<GIM>();
460 private int numInstantMessageThreads = 0;
464 lock (pendingInstantMessages) {
465 if (numInstantMessageThreads >= 4) {
469 pendingInstantMessages.Enqueue(gim);
471 ++ numInstantMessageThreads;
473 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
474 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
480 private void GridInstantMessageCompleted(IAsyncResult iar)
482 GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
499 SendGridInstantMessageViaXMLRPCAsync(im, result,
UUID.Zero);
500 }
catch (Exception e) {
501 m_log.Error(
"[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
503 lock (pendingInstantMessages) {
504 if (pendingInstantMessages.Count > 0) {
505 gim = pendingInstantMessages.Dequeue();
510 -- numInstantMessageThreads;
514 }
while (gim != null);
523 bool lookupAgent =
false;
525 lock (m_UserRegionMap)
527 if (m_UserRegionMap.ContainsKey(toAgentID))
530 upd.RegionID = m_UserRegionMap[toAgentID];
550 PresenceInfo[] presences = PresenceService.GetAgents(
new string[] { toAgentID.ToString() });
551 if (presences != null && presences.Length > 0)
571 HandleUndeliverableMessage(im, result);
578 HandleUndeliverableMessage(im, result);
585 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
589 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
593 msgdata[
"region_handle"] = 0;
594 bool imresult = doIMSending(reginfo, msgdata);
598 lock (m_UserRegionMap)
600 if (m_UserRegionMap.ContainsKey(toAgentID))
602 m_UserRegionMap[toAgentID] = upd.RegionID;
606 m_UserRegionMap.Add(toAgentID, upd.RegionID);
620 SendGridInstantMessageViaXMLRPCAsync(im, result,
626 m_log.WarnFormat(
"[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
627 HandleUndeliverableMessage(im, result);
632 HandleUndeliverableMessage(im, result);
644 ArrayList SendParams =
new ArrayList();
645 SendParams.Add(xmlrpcdata);
646 XmlRpcRequest GridReq =
new XmlRpcRequest(
"grid_instant_message", SendParams);
650 XmlRpcResponse GridResp = GridReq.Send(reginfo.ServerURI, 3000);
652 Hashtable responseData = (Hashtable)GridResp.Value;
654 if (responseData.ContainsKey(
"success"))
656 if ((
string)responseData[
"success"] ==
"TRUE")
670 catch (WebException e)
672 m_log.ErrorFormat(
"[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond " + e.ToString(), reginfo.
ServerURI.ToString());
709 Hashtable gim =
new Hashtable();
710 gim[
"from_agent_id"] = msg.fromAgentID.ToString();
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);
722 gim[
"from_group"] =
"TRUE";
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();
732 gim[
"binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
733 if (m_MessageKey !=
String.Empty)
734 gim[
"message_key"] = m_MessageKey;
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...
UndeliveredMessage OnUndeliveredMessage
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) ...