aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
diff options
context:
space:
mode:
authoronefang2019-05-19 21:24:15 +1000
committeronefang2019-05-19 21:24:15 +1000
commit5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch)
treea9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
parentAdd a build script. (diff)
downloadopensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip
opensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz
opensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2
opensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs297
1 files changed, 196 insertions, 101 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 2462ff8..efb9421 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -50,6 +50,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 private bool m_Enabled = false; 52 private bool m_Enabled = false;
53 protected string m_MessageKey = String.Empty;
53 protected List<Scene> m_Scenes = new List<Scene>(); 54 protected List<Scene> m_Scenes = new List<Scene>();
54 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>(); 55 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>();
55 56
@@ -69,14 +70,17 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
69 public virtual void Initialise(IConfigSource config) 70 public virtual void Initialise(IConfigSource config)
70 { 71 {
71 IConfig cnf = config.Configs["Messaging"]; 72 IConfig cnf = config.Configs["Messaging"];
72 if (cnf != null && cnf.GetString( 73 if (cnf != null)
73 "MessageTransferModule", "MessageTransferModule") !=
74 "MessageTransferModule")
75 { 74 {
76 m_log.Debug("[MESSAGE TRANSFER]: Disabled by configuration"); 75 if (cnf.GetString("MessageTransferModule",
77 return; 76 "MessageTransferModule") != "MessageTransferModule")
78 } 77 {
78 return;
79 }
79 80
81 m_MessageKey = cnf.GetString("MessageKey", String.Empty);
82 }
83 m_log.Debug("[MESSAGE TRANSFER]: Module enabled");
80 m_Enabled = true; 84 m_Enabled = true;
81 } 85 }
82 86
@@ -135,53 +139,45 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
135 { 139 {
136 UUID toAgentID = new UUID(im.toAgentID); 140 UUID toAgentID = new UUID(im.toAgentID);
137 141
142 if (toAgentID == UUID.Zero)
143 return;
144
145 IClientAPI client = null;
146
138 // Try root avatar only first 147 // Try root avatar only first
139 foreach (Scene scene in m_Scenes) 148 foreach (Scene scene in m_Scenes)
140 { 149 {
141// m_log.DebugFormat(
142// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
143// toAgentID.ToString(), scene.RegionInfo.RegionName);
144
145 ScenePresence sp = scene.GetScenePresence(toAgentID); 150 ScenePresence sp = scene.GetScenePresence(toAgentID);
146 if (sp != null && !sp.IsChildAgent) 151 if (sp != null && !sp.IsDeleted && sp.ControllingClient.IsActive)
147 { 152 {
148 // Local message 153 // actualy don't send via child agents
149// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); 154 // ims can be complex things, and not sure viewers will not mess up
150 155 if(sp.IsChildAgent)
151 sp.ControllingClient.SendInstantMessage(im); 156 continue;
152 157
153 // Message sent 158 client = sp.ControllingClient;
154 result(true); 159 if(!sp.IsChildAgent)
155 return; 160 break;
156 } 161 }
157 } 162 }
158 163
159 // try child avatar second 164 if(client != null)
160 foreach (Scene scene in m_Scenes)
161 { 165 {
162// m_log.DebugFormat( 166 // Local message
163// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); 167// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
164
165 ScenePresence sp = scene.GetScenePresence(toAgentID);
166 if (sp != null)
167 {
168 // Local message
169// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
170 168
171 sp.ControllingClient.SendInstantMessage(im); 169 client.SendInstantMessage(im);
172 170
173 // Message sent 171 // Message sent
174 result(true); 172 result(true);
175 return; 173 return;
176 }
177 } 174 }
178
179// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 175// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
180 176
181 SendGridInstantMessageViaXMLRPC(im, result); 177 SendGridInstantMessageViaXMLRPC(im, result);
182 } 178 }
183 179
184 public void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result) 180 public virtual void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result)
185 { 181 {
186 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; 182 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
187 183
@@ -211,10 +207,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
211 protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient) 207 protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient)
212 { 208 {
213 bool successful = false; 209 bool successful = false;
214 210
215 // TODO: For now, as IMs seem to be a bit unreliable on OSGrid, catch all exception that 211 // TODO: For now, as IMs seem to be a bit unreliable on OSGrid, catch all exception that
216 // happen here and aren't caught and log them. 212 // happen here and aren't caught and log them.
217 try 213 try
218 { 214 {
219 // various rational defaults 215 // various rational defaults
220 UUID fromAgentID = UUID.Zero; 216 UUID fromAgentID = UUID.Zero;
@@ -236,7 +232,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
236 float pos_z = 0; 232 float pos_z = 0;
237 //m_log.Info("Processing IM"); 233 //m_log.Info("Processing IM");
238 234
239
240 Hashtable requestData = (Hashtable)request.Params[0]; 235 Hashtable requestData = (Hashtable)request.Params[0];
241 // Check if it's got all the data 236 // Check if it's got all the data
242 if (requestData.ContainsKey("from_agent_id") 237 if (requestData.ContainsKey("from_agent_id")
@@ -249,6 +244,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
249 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") 244 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
250 && requestData.ContainsKey("binary_bucket")) 245 && requestData.ContainsKey("binary_bucket"))
251 { 246 {
247 if (m_MessageKey != String.Empty)
248 {
249 XmlRpcResponse error_resp = new XmlRpcResponse();
250 Hashtable error_respdata = new Hashtable();
251 error_respdata["success"] = "FALSE";
252 error_resp.Value = error_respdata;
253
254 if (!requestData.Contains("message_key"))
255 return error_resp;
256 if (m_MessageKey != (string)requestData["message_key"])
257 return error_resp;
258 }
259
252 // Do the easy way of validating the UUIDs 260 // Do the easy way of validating the UUIDs
253 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); 261 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
254 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); 262 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
@@ -382,7 +390,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
382 gim.Position = Position; 390 gim.Position = Position;
383 gim.binaryBucket = binaryBucket; 391 gim.binaryBucket = binaryBucket;
384 392
385
386 // Trigger the Instant message in the scene. 393 // Trigger the Instant message in the scene.
387 foreach (Scene scene in m_Scenes) 394 foreach (Scene scene in m_Scenes)
388 { 395 {
@@ -425,104 +432,191 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
425 return resp; 432 return resp;
426 } 433 }
427 434
435
428 /// <summary> 436 /// <summary>
429 /// delegate for sending a grid instant message asynchronously 437 /// delegate for sending a grid instant message asynchronously
430 /// </summary> 438 /// </summary>
431 public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result); 439 private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
440
441 private class GIM {
442 public GridInstantMessage im;
443 public MessageResultNotification result;
444 };
432 445
433 protected virtual void GridInstantMessageCompleted(IAsyncResult iar) 446 private Queue<GIM> pendingInstantMessages = new Queue<GIM>();
447 private int numInstantMessageThreads = 0;
448
449 private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
434 { 450 {
435 GridInstantMessageDelegate icon = 451 lock (pendingInstantMessages) {
436 (GridInstantMessageDelegate)iar.AsyncState; 452 if (numInstantMessageThreads >= 4) {
437 icon.EndInvoke(iar); 453 GIM gim = new GIM();
454 gim.im = im;
455 gim.result = result;
456 pendingInstantMessages.Enqueue(gim);
457 } else {
458 ++ numInstantMessageThreads;
459 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
460 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
461 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
462 }
463 }
438 } 464 }
439 465
440 466
441 protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) 467 private void GridInstantMessageCompleted(IAsyncResult iar)
442 { 468 {
443 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; 469 GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
444 470 d.EndInvoke(iar);
445 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
446 } 471 }
447 472
448 /// <summary> 473 /// <summary>
449 /// Internal SendGridInstantMessage over XMLRPC method. 474 /// Internal SendGridInstantMessage over XMLRPC method.
450 /// </summary> 475 /// </summary>
451 /// <remarks> 476
452 /// This is called from within a dedicated thread. 477 /// <param name="prevRegionHandle">
453 /// </remarks> 478 /// Pass in 0 the first time this method is called. It will be called recursively with the last
454 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result) 479 /// regionhandle tried
480 /// </param>
481 private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
482 {
483 GIM gim;
484 do {
485 try {
486 SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
487 } catch (Exception e) {
488 m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
489 }
490 lock (pendingInstantMessages) {
491 if (pendingInstantMessages.Count > 0) {
492 gim = pendingInstantMessages.Dequeue();
493 im = gim.im;
494 result = gim.result;
495 } else {
496 gim = null;
497 -- numInstantMessageThreads;
498 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
499 }
500 }
501 } while (gim != null);
502 }
503
504 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
455 { 505 {
506
456 UUID toAgentID = new UUID(im.toAgentID); 507 UUID toAgentID = new UUID(im.toAgentID);
457 UUID regionID; 508 PresenceInfo upd = null;
458 bool needToLookupAgent; 509 bool lookupAgent = false;
459 510
460 lock (m_UserRegionMap) 511 lock (m_UserRegionMap)
461 needToLookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID);
462
463 while (true)
464 { 512 {
465 if (needToLookupAgent) 513 if (m_UserRegionMap.ContainsKey(toAgentID))
466 { 514 {
467 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); 515 upd = new PresenceInfo();
468 516 upd.RegionID = m_UserRegionMap[toAgentID];
469 UUID foundRegionID = UUID.Zero;
470 517
471 if (presences != null) 518 // We need to compare the current regionhandle with the previous region handle
519 // or the recursive loop will never end because it will never try to lookup the agent again
520 if (prevRegionID == upd.RegionID)
472 { 521 {
473 foreach (PresenceInfo p in presences) 522 lookupAgent = true;
474 {
475 if (p.RegionID != UUID.Zero)
476 {
477 foundRegionID = p.RegionID;
478 break;
479 }
480 }
481 } 523 }
482
483 // If not found or the found region is the same as the last lookup, then message is undeliverable
484 if (foundRegionID == UUID.Zero || foundRegionID == regionID)
485 break;
486 else
487 regionID = foundRegionID;
488 } 524 }
489 525 else
490 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID);
491 if (reginfo == null)
492 { 526 {
493 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); 527 lookupAgent = true;
494 break;
495 } 528 }
529 }
496 530
497 // Try to send the message to the agent via the retrieved region.
498 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
499 msgdata["region_handle"] = 0;
500 bool imresult = doIMSending(reginfo, msgdata);
501 531
502 // If the message delivery was successful, then cache the entry. 532 // Are we needing to look-up an agent?
503 if (imresult) 533 if (lookupAgent)
534 {
535 // Non-cached user agent lookup.
536 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
537 if (presences != null && presences.Length > 0)
504 { 538 {
505 lock (m_UserRegionMap) 539 foreach (PresenceInfo p in presences)
506 { 540 {
507 m_UserRegionMap[toAgentID] = regionID; 541 if (p.RegionID != UUID.Zero)
542 {
543 upd = p;
544 break;
545 }
508 } 546 }
509 result(true);
510 return;
511 } 547 }
512 548
513 // If we reach this point in the first iteration of the while, then we may have unsuccessfully tried 549 if (upd != null)
514 // to use a locally cached region ID. All subsequent attempts need to lookup agent details from 550 {
515 // the presence service. 551 // check if we've tried this before..
516 needToLookupAgent = true; 552 // This is one way to end the recursive loop
553 //
554 if (upd.RegionID == prevRegionID)
555 {
556 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
557 HandleUndeliverableMessage(im, result);
558 return;
559 }
560 }
561 else
562 {
563 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
564 HandleUndeliverableMessage(im, result);
565 return;
566 }
517 } 567 }
518 568
519 // If we reached this point then the message was not deliverable. Remove the bad cache entry and 569 if (upd != null)
520 // signal the delivery failure. 570 {
521 lock (m_UserRegionMap) 571 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
522 m_UserRegionMap.Remove(toAgentID); 572 upd.RegionID);
573 if (reginfo != null)
574 {
575 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
576 // Not actually used anymore, left in for compatibility
577 // Remove at next interface change
578 //
579 msgdata["region_handle"] = 0;
580 bool imresult = doIMSending(reginfo, msgdata);
581 if (imresult)
582 {
583 // IM delivery successful, so store the Agent's location in our local cache.
584 lock (m_UserRegionMap)
585 {
586 if (m_UserRegionMap.ContainsKey(toAgentID))
587 {
588 m_UserRegionMap[toAgentID] = upd.RegionID;
589 }
590 else
591 {
592 m_UserRegionMap.Add(toAgentID, upd.RegionID);
593 }
594 }
595 result(true);
596 }
597 else
598 {
599 // try again, but lookup user this time.
600 // Warning, this must call the Async version
601 // of this method or we'll be making thousands of threads
602 // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
603 // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
523 604
524 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); 605 // This is recursive!!!!!
525 HandleUndeliverableMessage(im, result); 606 SendGridInstantMessageViaXMLRPCAsync(im, result,
607 upd.RegionID);
608 }
609 }
610 else
611 {
612 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
613 HandleUndeliverableMessage(im, result);
614 }
615 }
616 else
617 {
618 HandleUndeliverableMessage(im, result);
619 }
526 } 620 }
527 621
528 /// <summary> 622 /// <summary>
@@ -622,8 +716,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
622 gim["position_z"] = msg.Position.Z.ToString(); 716 gim["position_z"] = msg.Position.Z.ToString();
623 gim["region_id"] = new UUID(msg.RegionID).ToString(); 717 gim["region_id"] = new UUID(msg.RegionID).ToString();
624 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); 718 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
719 if (m_MessageKey != String.Empty)
720 gim["message_key"] = m_MessageKey;
625 return gim; 721 return gim;
626 } 722 }
627
628 } 723 }
629} 724}