fix infinite recursion loop in SendGridInstantMessageViaXMLRPCAsync()
parent
0faba7dc33
commit
cecb446e0e
|
@ -428,7 +428,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
|
|||
/// <summary>
|
||||
/// delegate for sending a grid instant message asynchronously
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="prevRegionHandle">
|
||||
/// Pass in 0 the first time this method is called. It will be called recursively with the last
|
||||
/// regionhandle tried
|
||||
/// </param>
|
||||
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);
|
||||
m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
lock (m_UserRegionMap)
|
||||
{
|
||||
m_UserRegionMap[toAgentID] = regionID;
|
||||
}
|
||||
result(true);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Message delivery failed.
|
||||
* If we just looked up what region the agent is in, message is undeliverable.
|
||||
*/
|
||||
if (lookupAgent)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We used a cached entry that we now know is bad.
|
||||
* Try again by searching the grid for the user.
|
||||
*/
|
||||
lookupAgent = true;
|
||||
}
|
||||
|
||||
if (upd != null)
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID,
|
||||
upd.RegionID);
|
||||
if (reginfo != null)
|
||||
{
|
||||
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
|
||||
{
|
||||
// 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
|
||||
m_UserRegionMap.Remove(toAgentID);
|
||||
}
|
||||
|
||||
// This is recursive!!!!!
|
||||
SendGridInstantMessageViaXMLRPCAsync(im, result,
|
||||
upd.RegionID);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
|
||||
HandleUndeliveredMessage(im, result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleUndeliveredMessage(im, result);
|
||||
}
|
||||
// m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
|
||||
HandleUndeliveredMessage(im, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
Loading…
Reference in New Issue