From cecb446e0e91ede0b05ea9cf40c1313782241f3d Mon Sep 17 00:00:00 2001
From: Kunta Kinte
Date: Tue, 29 Apr 2014 07:26:07 -0700
Subject: fix infinite recursion loop in SendGridInstantMessageViaXMLRPCAsync()
---
.../Avatar/InstantMessage/MessageTransferModule.cs | 178 +++++++++------------
1 file changed, 79 insertions(+), 99 deletions(-)
(limited to 'OpenSim/Region/CoreModules')
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 40a400f..4f8e2cd 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -428,7 +428,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
///
/// delegate for sending a grid instant message asynchronously
///
- public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID);
+ public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
protected virtual void GridInstantMessageCompleted(IAsyncResult iar)
{
@@ -442,138 +442,118 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
{
GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync;
- d.BeginInvoke(im, result, UUID.Zero, GridInstantMessageCompleted, d);
+ d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
}
///
- /// Recursive SendGridInstantMessage over XMLRPC method.
+ /// Internal SendGridInstantMessage over XMLRPC method.
/// This is called from within a dedicated thread.
- /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from
- /// itself, prevRegionHandle will be the last region handle that we tried to send.
- /// If the handles are the same, we look up the user's location using the grid.
- /// If the handles are still the same, we end. The send failed.
///
- ///
- /// Pass in 0 the first time this method is called. It will be called recursively with the last
- /// regionhandle tried
- ///
- protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
+ private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result)
{
UUID toAgentID = new UUID(im.toAgentID);
+ UUID regionID;
+ bool lookupAgent;
- PresenceInfo upd = null;
-
- bool lookupAgent = false;
-
+ /*
+ * Try to get what region the agent is in from the cache.
+ */
lock (m_UserRegionMap)
{
- if (m_UserRegionMap.ContainsKey(toAgentID))
- {
- upd = new PresenceInfo();
- upd.RegionID = m_UserRegionMap[toAgentID];
-
- // We need to compare the current regionhandle with the previous region handle
- // or the recursive loop will never end because it will never try to lookup the agent again
- if (prevRegionID == upd.RegionID)
- {
- lookupAgent = true;
- }
- }
- else
- {
- lookupAgent = true;
- }
+ lookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID);
}
-
- // Are we needing to look-up an agent?
- if (lookupAgent)
+ while (true)
{
- // Non-cached user agent lookup.
- PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
- if (presences != null && presences.Length > 0)
+
+ /*
+ * If not in cache, try to find out what region the agent is in.
+ * Also do this if we know the existing cache entry is bad.
+ */
+ if (lookupAgent)
{
- foreach (PresenceInfo p in presences)
+ PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
+
+ regionID = UUID.Zero;
+ if (presences != null)
{
- if (p.RegionID != UUID.Zero)
+ foreach (PresenceInfo p in presences)
{
- upd = p;
- break;
+ if (p.RegionID != UUID.Zero)
+ {
+ regionID = p.RegionID;
+ break;
+ }
}
}
- }
- if (upd != null)
- {
- // check if we've tried this before..
- // This is one way to end the recursive loop
- //
- if (upd.RegionID == prevRegionID)
+ // If not found, message is undeliverable
+ if (regionID == UUID.Zero)
{
- // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
- HandleUndeliveredMessage(im, result);
- return;
+ break;
}
}
- else
+
+ /*
+ * Try to find out about region.
+ * If unable, message is undeliverable.
+ */
+ GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID);
+ if (reginfo == null)
{
- // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
- HandleUndeliveredMessage(im, result);
- return;
+ m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID);
+ break;
}
- }
- if (upd != null)
- {
- GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID,
- upd.RegionID);
- if (reginfo != null)
+ /*
+ * Try to send message to agent in the region.
+ */
+ Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
+ msgdata["region_handle"] = 0;
+ bool imresult = doIMSending(reginfo, msgdata);
+
+ /*
+ * If message delivery successful, save cache entry because we know it is good.
+ * Then tell caller message has been delivered and we are done.
+ */
+ if (imresult)
{
- Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
- // Not actually used anymore, left in for compatibility
- // Remove at next interface change
- //
- msgdata["region_handle"] = 0;
- bool imresult = doIMSending(reginfo, msgdata);
- if (imresult)
- {
- // IM delivery successful, so store the Agent's location in our local cache.
- lock (m_UserRegionMap)
- {
- if (m_UserRegionMap.ContainsKey(toAgentID))
- {
- m_UserRegionMap[toAgentID] = upd.RegionID;
- }
- else
- {
- m_UserRegionMap.Add(toAgentID, upd.RegionID);
- }
- }
- result(true);
- }
- else
+ lock (m_UserRegionMap)
{
- // try again, but lookup user this time.
- // Warning, this must call the Async version
- // of this method or we'll be making thousands of threads
- // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
- // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
-
- // This is recursive!!!!!
- SendGridInstantMessageViaXMLRPCAsync(im, result,
- upd.RegionID);
+ m_UserRegionMap[toAgentID] = regionID;
}
+ result(true);
+ return;
}
- else
+
+ /*
+ * Message delivery failed.
+ * If we just looked up what region the agent is in, message is undeliverable.
+ */
+ if (lookupAgent)
{
- m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
- HandleUndeliveredMessage(im, result);
+ break;
}
+
+ /*
+ * We used a cached entry that we now know is bad.
+ * Try again by searching the grid for the user.
+ */
+ lookupAgent = true;
}
- else
+
+ /*
+ * Message is undeliverable for one reason or another.
+ * Remove possible bad entry from cache.
+ * Then inform caller that the message is undeliverable.
+ */
+ lock (m_UserRegionMap)
{
- HandleUndeliveredMessage(im, result);
+ m_UserRegionMap.Remove(toAgentID);
}
+
+ // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
+ HandleUndeliveredMessage(im, result);
}
///
--
cgit v1.1