public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); m_log.DebugFormat("[INSTANT MESSAGE]: Attempting delivery of IM from {0} to {1}", im.fromAgentName, toAgentID.ToString()); // Try root avatar only first foreach (Scene scene in m_Scenes) { if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { m_log.DebugFormat("[INSTANT MESSAGE]: Looking for {0} in {1}", toAgentID.ToString(), scene.RegionInfo.RegionName); // Local message ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; if (!user.IsChildAgent) { m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); user.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } } // try child avatar second foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { // Local message ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); user.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } if (m_Gridmode) { //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering via grid"); // Still here, try send via Grid SendGridInstantMessageViaXMLRPC(im, result); return; } HandleUndeliveredMessage(im, result); return; }
/// <summary> /// Internal SendGridInstantMessage over XMLRPC method. /// </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> private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result) { GIM gim; do { try { SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero); } catch (Exception e) { m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message); } lock (pendingInstantMessages) { if (pendingInstantMessages.Count > 0) { gim = pendingInstantMessages.Dequeue(); im = gim.im; result = gim.result; } else { gim = null; --numInstantMessageThreads; //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads); } } } while (gim != null); }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); try { // Try root avatar only first m_Scenes.ForEach(delegate(Scene scene) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", // toAgentID.ToString(), scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null && !sp.IsChildAgent) { // Local message // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); throw new ThreadedClasses.ReturnValueException <bool>(true); } }); // try child avatar second m_Scenes.ForEach(delegate(Scene scene) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null) { // Local message // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); throw new ThreadedClasses.ReturnValueException <bool>(true); } }); } catch (ThreadedClasses.ReturnValueException <bool> ) { return; } // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); SendGridInstantMessageViaXMLRPC(im, result); }
private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) { GIMData gim = new GIMData() { im = im, result = result }; IMXMLRPCSendWorkers.Enqueue(gim); }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); // Try root avatar only first foreach (Scene scene in m_Scenes) { if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", // toAgentID.ToString(), scene.RegionInfo.RegionName); ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; if (!user.IsChildAgent) { // Local message m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); user.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } } // try child avatar second foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { // Local message ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); user.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); SendGridInstantMessageViaXMLRPC(im, result); return; }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); if (toAgentID == UUID.Zero) { return; } // Try root avatar only first foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", // toAgentID.ToString(), scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null && !sp.IsChildAgent) { // Local message // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } // try child avatar second foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null) { // Local message // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); SendGridInstantMessageViaXMLRPC(im, result); }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); if (toAgentID == UUID.Zero) { return; } IClientAPI client = null; // Try root avatar only first foreach (Scene scene in m_Scenes) { ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null && !sp.IsDeleted && sp.ControllingClient.IsActive) { // actualy don't send via child agents // ims can be complex things, and not sure viewers will not mess up if (sp.IsChildAgent) { continue; } client = sp.ControllingClient; if (!sp.IsChildAgent) { break; } } } if (client != null) { // Local message // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); client.SendInstantMessage(im); // Message sent result(true); return; } // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); SendGridInstantMessageViaXMLRPC(im, result); }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); // Try root avatar only first - incorrect now, see below foreach (Scene scene in m_Scenes) { IScenePresence user; if (scene.TryGetScenePresence(toAgentID, out user)) { user.ControllingClient.SendInstantMessage(im); return; } } //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); SendGridInstantMessageViaXMLRPC(im, result); }
private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) { UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; // If this event has handlers, then the IM will be considered // delivered. This will suppress the error message. // if (handlerUndeliveredMessage != null) { handlerUndeliveredMessage(im); result(true); return; } m_log.WarnFormat("[INSTANT MESSAGE]: Message undeliverable and no undeliverable message handler for message from {0} to {1}", im.fromAgentID, im.toAgentID); result(false); }
private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) { UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; // If this event has handlers, then the IM will be considered // delivered. This will suppress the error message. // if (handlerUndeliveredMessage != null) { handlerUndeliveredMessage(im); result(true); return; } //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable"); result(false); }
private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) { lock (pendingInstantMessages) { if (numInstantMessageThreads >= 4) { GIM gim = new GIM(); gim.im = im; gim.result = result; pendingInstantMessages.Enqueue(gim); } else { ++numInstantMessageThreads; //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads); GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain; d.BeginInvoke(im, result, GridInstantMessageCompleted, d); } } }
private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) { UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; // If this event has handlers, then an IM from an agent will be // considered delivered. This will suppress the error message. // if (handlerUndeliveredMessage != null) { handlerUndeliveredMessage(im); if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) { result(true); } else { result(false); } return; } //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable"); result(false); }
/// <summary> /// Recursive 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, ulong prevRegionHandle, int tries) { UserAgentData upd = null; bool lookupAgent = false; UUID toAgentID = new UUID(im.toAgentID); if (tries > 5) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Retries exhausted - Unable to deliver an instant message to {0}", toAgentID.ToString()); return; } if (m_DebugLevel >= 2) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} tries={1}", prevRegionHandle, tries); } lock (m_UserRegionMap) { if (m_UserRegionMap.ContainsKey(toAgentID)) { upd = new UserAgentData(); upd.AgentOnline = true; upd.Handle = 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 (prevRegionHandle == upd.Handle) { lookupAgent = true; if (m_DebugLevel >= 2) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} tries={1} in region map, same region, requires lookup", prevRegionHandle, tries); } } else if (prevRegionHandle == 0) { if (m_DebugLevel >= 1) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} tries={1} in region map, using {2}, no lookup", prevRegionHandle, tries, upd.Handle); } } else { if (m_DebugLevel >= 1) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} tries={1} in region map, different region, no lookup", prevRegionHandle, tries); } } } else { lookupAgent = true; if (m_DebugLevel >= 2) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} tries={1} not in region map, requires lookup", prevRegionHandle, tries); } } } // Are we needing to look-up an agent? if (lookupAgent) { // Non-cached user agent lookup. upd = m_Scenes[0].CommsManager.UserService.GetUserAgent(toAgentID, true); if (upd != null) { // check if we've tried this before.. // This is one way to end the recursive loop // if (upd.Handle == prevRegionHandle) { if (m_DebugLevel >= 1) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} still, tries={1}", upd.Handle, tries); } HandleUndeliveredMessage(im, result); return; } else { if (m_DebugLevel >= 1) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} now, tries={1} lookup success", upd.Handle, tries); } } } else { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Unable to deliver an instant message to {0} (user lookup failed).", toAgentID.ToString()); HandleUndeliveredMessage(im, result); return; } } if (upd != null) { if (upd.AgentOnline) { RegionInfo reginfo = m_Scenes[0].SceneGridService.RequestNeighbouringRegionInfo(upd.Handle); if (reginfo != null) { if (m_DebugLevel >= 2) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} now, sending grid IM", upd.Handle); } 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.Handle; if (m_DebugLevel >= 1) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} success, updating map", upd.Handle); } } else { m_UserRegionMap.Add(toAgentID, upd.Handle); if (m_DebugLevel >= 1) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} success, adding to map", upd.Handle); } } } 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 // This is recursive!!!!! if (m_DebugLevel >= 2) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} failed, retrying recursively", upd.Handle); } SendGridInstantMessageViaXMLRPCAsync(im, result, upd.Handle, ++tries); } } else { if (m_DebugLevel >= 2) { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}, will retry", upd.Handle); } SendGridInstantMessageViaXMLRPCAsync(im, result, upd.Handle, ++tries); } } else { if (m_DebugLevel >= 1) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} user offline.", upd.Handle); } HandleUndeliveredMessage(im, result); } } else { if (m_DebugLevel >= 1) { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find user {0}", toAgentID); } HandleUndeliveredMessage(im, result); } }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID fromAgentID = new UUID(im.fromAgentID); UUID toAgentID = new UUID(im.toAgentID); foreach (Scene scene in m_Scenes) { if (!scene.EventManager.TriggerOnBeforeSendInstantMessage(im)) { m_log.WarnFormat("[INSTANT MESSAGE]: Outbound IM blocked by module"); return; } // Check for muted senders in specific IM cases. if (m_muteListModule == null) m_muteListModule = scene.RequestModuleInterface<IMuteListModule>(); if (m_muteListModule != null) if ((im.dialog == (int)InstantMessageDialog.MessageFromAgent) || (im.dialog == (int)InstantMessageDialog.MessageFromObject)) if (m_muteListModule.IsMuted(fromAgentID, toAgentID)) // owner ID is in fromAgentID in case of IMs from objects return; // recipient has sender muted. } //m_log.DebugFormat("[INSTANT MESSAGE]: Attempting delivery of IM from {0} to {1}", im.fromAgentName, toAgentID.ToString()); // Try root avatar only first foreach (Scene scene in m_Scenes) { if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { //m_log.DebugFormat("[INSTANT MESSAGE]: Looking for {0} in {1}", toAgentID.ToString(), scene.RegionInfo.RegionName); // Local message ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; if (!user.IsChildAgent) { //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); user.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } } // try child avatar second foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { // Local message ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); user.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } if (m_Gridmode) { //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering via grid"); // Still here, try send via Grid SendGridInstantMessageViaXMLRPC(im, result); return; } HandleUndeliveredMessage(im, result); return; }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); // Try root avatar only first - incorrect now, see below foreach (Scene scene in m_Scenes) { if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { // Local message ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; user.ControllingClient.SendInstantMessage(im); return; } } //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); SendGridInstantMessageViaXMLRPC(im, result); }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); m_log.DebugFormat("[INSTANT MESSAGE]: Attempting delivery of IM from {0} to {1}", im.fromAgentName, toAgentID.ToString()); // Try root avatar only first foreach (Scene scene in m_Scenes) { if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { m_log.DebugFormat("[INSTANT MESSAGE]: Looking for {0} in {1}", toAgentID.ToString(), scene.RegionInfo.RegionName); // Local message ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; if (!user.IsChildAgent) { m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); user.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } } // try child avatar second foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { // Local message ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); user.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } SendGridInstantMessageViaXMLRPC(im, result); return; }
protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) { GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; d.BeginInvoke(im, result, UUID.Zero, GridInstantMessageCompleted, d); }
/// <summary> /// Recursive 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, ulong prevRegionHandle, int tries) { UserAgentData upd = null; bool lookupAgent = false; UUID toAgentID = new UUID(im.toAgentID); if (tries > 5) { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Retries exhausted - Unable to deliver an instant message to {0}", toAgentID.ToString()); return; } if (m_DebugLevel >= 2) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} tries={1}", prevRegionHandle, tries); lock (m_UserRegionMap) { if (m_UserRegionMap.ContainsKey(toAgentID)) { upd = new UserAgentData(); upd.AgentOnline = true; upd.Handle = 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 (prevRegionHandle == upd.Handle) { lookupAgent = true; if (m_DebugLevel >= 2) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} tries={1} in region map, same region, requires lookup", prevRegionHandle, tries); } else if (prevRegionHandle == 0) { if (m_DebugLevel >= 1) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} tries={1} in region map, using {2}, no lookup", prevRegionHandle, tries, upd.Handle); } else { if (m_DebugLevel >= 1) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} tries={1} in region map, different region, no lookup", prevRegionHandle, tries); } } else { lookupAgent = true; if (m_DebugLevel >= 2) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} tries={1} not in region map, requires lookup", prevRegionHandle, tries); } } // Are we needing to look-up an agent? if (lookupAgent) { // Non-cached user agent lookup. upd = m_Scenes[0].CommsManager.UserService.GetUserAgent(toAgentID,true); if (upd != null) { // check if we've tried this before.. // This is one way to end the recursive loop // if (upd.Handle == prevRegionHandle) { if (m_DebugLevel >= 1) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} still, tries={1}", upd.Handle, tries); HandleUndeliveredMessage(im, result); return; } else { if (m_DebugLevel >= 1) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} now, tries={1} lookup success", upd.Handle, tries); } } else { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Unable to deliver an instant message to {0} (user lookup failed).", toAgentID.ToString()); HandleUndeliveredMessage(im, result); return; } } if (upd != null) { if (upd.AgentOnline) { RegionInfo reginfo = m_Scenes[0].SceneGridService.RequestNeighbouringRegionInfo(upd.Handle); if (reginfo != null) { if (m_DebugLevel >= 2) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} now, sending grid IM", upd.Handle); 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.Handle; if (m_DebugLevel >= 1) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} success, updating map", upd.Handle); } else { m_UserRegionMap.Add(toAgentID, upd.Handle); if (m_DebugLevel >= 1) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} success, adding to map", upd.Handle); } } 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 // This is recursive!!!!! if (m_DebugLevel >= 2) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} failed, retrying recursively", upd.Handle); SendGridInstantMessageViaXMLRPCAsync(im, result, upd.Handle, ++tries); } } else { if (m_DebugLevel >= 2) m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}, will retry", upd.Handle); SendGridInstantMessageViaXMLRPCAsync(im, result, upd.Handle, ++tries); } } else { if (m_DebugLevel >= 1) m_log.ErrorFormat("[GRID INSTANT MESSAGE]: region={0} user offline.", upd.Handle); HandleUndeliveredMessage(im, result); } } else { if (m_DebugLevel >= 1) m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find user {0}", toAgentID); HandleUndeliveredMessage(im, result); } }
/// <summary> /// Recursive 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, GridRegion prevRegion) { UUID toAgentID = im.toAgentID; string HTTPPath = ""; Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); lock (IMUsersCache) { if (!IMUsersCache.TryGetValue(toAgentID, out HTTPPath)) HTTPPath = ""; } if (HTTPPath != "") { //We've tried to send an IM to them before, pull out their info //Send the IM to their last location if (!doIMSending(HTTPPath, msgdata)) { //If this fails, the user has either moved from their stored location or logged out //Since it failed, let it look them up again and rerun lock (IMUsersCache) { IMUsersCache.Remove(toAgentID); } //Clear the path and let it continue trying again. HTTPPath = ""; } else { //Send the IM, and it made it to the user, return true result(true); return; } } //Now query the grid server for the agent //Ask for the user new style first string[] AgentLocations = m_Scenes[0].RequestModuleInterface<IAgentInfoService>().GetAgentsLocations(new string[] { toAgentID.ToString() }); //If this is false, this doesn't exist on the presence server and we use the legacy way if (AgentLocations.Length > 0) { //No agents, so this user is offline if (AgentLocations[0] == "NotOnline") { lock (IMUsersCache) { //Remove them so we keep testing against the db IMUsersCache.Remove(toAgentID); } m_log.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } else //Found the agent, use this location HTTPPath = AgentLocations[0]; } //We found the agent's location, now ask them about the user if (HTTPPath != "") { if (!doIMSending(HTTPPath, msgdata)) { //It failed, stop now lock (IMUsersCache) { //Remove them so we keep testing against the db IMUsersCache.Remove(toAgentID); } m_log.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message as the region could not be found"); HandleUndeliveredMessage(im, result); return; } else { //Add to the cache if(!IMUsersCache.ContainsKey(toAgentID)) IMUsersCache.Add (toAgentID, HTTPPath); //Send the IM, and it made it to the user, return true result(true); return; } } else { //Couldn't find them, stop for now lock (IMUsersCache) { //Remove them so we keep testing against the db IMUsersCache.Remove(toAgentID); } m_log.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message as the region could not be found"); HandleUndeliveredMessage(im, result); } }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); // Try root avatar only first foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", // toAgentID.ToString(), scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null && !sp.IsChildAgent) { // Local message // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } // try child avatar second foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null) { // Local message // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); SendGridInstantMessageViaXMLRPC(im, result); return; }
/// <summary> /// Recursive 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) { UUID toAgentID = new UUID(im.toAgentID); PresenceInfo upd = null; bool lookupAgent = false; 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) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: agentInRegionMap. prevRegion==upd.Region settingLookupAgentTrue, agentID={1}, regionID={2}", LogHeader, toAgentID, prevRegionID); lookupAgent = true; } } else { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: agentNOTInRegionMap. setting LookupAgentTrue", LogHeader); lookupAgent = true; } } // Are we needing to look-up an agent? if (lookupAgent) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: lookupAgent IS TRUE", LogHeader); // Non-cached user agent lookup. PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) { foreach (PresenceInfo p in presences) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: got presences. p.RegionID={1}", LogHeader, p.RegionID); // Sometimes we get more than 1 session querying a single agent ID! Filter for the correct agent ID. if (p.UserID == toAgentID.ToString() && p.RegionID != UUID.Zero) { upd = p; break; } } } if (upd != null) { // check if we've tried this before.. // This is one way to end the recursive loop // if (upd.RegionID == prevRegionID) { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); m_log.DebugFormat("{0} Unable to deliver instant message: regionID==prevRegionID: regionID={1}, agentID={2}", LogHeader, prevRegionID, toAgentID); HandleUndeliveredMessage(im, result); return; } } else { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); m_log.DebugFormat("{0} Unable to deliver instant message: lookupAgent=true, upd==null, agentID={1}", LogHeader, toAgentID); HandleUndeliveredMessage(im, result); return; } } if (upd != null) { GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID); if (reginfo != null) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: regInfoNotNull, regID={1}, regNam={2}, regURI={3}, regPort={4}", LogHeader, reginfo.RegionID, reginfo.RegionName, reginfo.ServerURI, reginfo.HttpPort); 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_log.DebugFormat("{0} SendGridInstMgsViaXMLRPCAsync: Updating RegionMap: agent={1}, reg={2}", LogHeader, toAgentID, upd.RegionID); m_UserRegionMap[toAgentID] = upd.RegionID; } else { m_log.DebugFormat("{0} SendGridInstMgsViaXMLRPCAsync: Add RegionMap: agent={1}, reg={2}", LogHeader, toAgentID, upd.RegionID); 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 // This is recursive!!!!! m_log.DebugFormat("{0} SendGridInstMgsViaXMLRPCAsync: Calling me recursively. region={1}", LogHeader, upd.RegionID); SendGridInstantMessageViaXMLRPCAsync(im, result, upd.RegionID); } } else { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); m_log.DebugFormat("{0} Unable to deliver instant message: regionInfo==null, lookupAgent={1}, agentid={2}, region={3}", LogHeader, lookupAgent, toAgentID, upd.RegionID); HandleUndeliveredMessage(im, result); } } else { m_log.DebugFormat("{0} Unable to deliver instant message: upd==null, lookupAgent={1}, agentid={2}", LogHeader, lookupAgent, toAgentID); HandleUndeliveredMessage(im, result); } }
/// <summary> /// Recursive 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, GridRegion prevRegion) { UUID toAgentID = new UUID(im.toAgentID); string HTTPPath = ""; Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); lock (IMUsersCache) { if (!IMUsersCache.TryGetValue(toAgentID, out HTTPPath)) { HTTPPath = ""; } } if (HTTPPath != "") { //We've tried to send an IM to them before, pull out their info //Send the IM to their last location if (!doIMSending(HTTPPath, msgdata)) { //If this fails, the user has either moved from their stored location or logged out //Since it failed, let it look them up again and rerun lock (IMUsersCache) { IMUsersCache.Remove(toAgentID); } //Clear the path and let it continue trying again. HTTPPath = ""; } else { //Send the IM, and it made it to the user, return true result(true); return; } } //Now query the grid server for the agent //Ask for the user new style first string[] AgentLocations = m_Scenes[0].RequestModuleInterface <IAgentInfoService>().GetAgentsLocations(new string[] { toAgentID.ToString() }); //If this is false, this doesn't exist on the presence server and we use the legacy way if (AgentLocations.Length > 0) { //No agents, so this user is offline if (AgentLocations[0] == "NotOnline") { lock (IMUsersCache) { //Remove them so we keep testing against the db IMUsersCache.Remove(toAgentID); } m_log.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } else //Found the agent, use this location { HTTPPath = AgentLocations[0]; } } //We found the agent's location, now ask them about the user if (HTTPPath != "") { if (!doIMSending(HTTPPath, msgdata)) { //It failed, stop now lock (IMUsersCache) { //Remove them so we keep testing against the db IMUsersCache.Remove(toAgentID); } m_log.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message as the region could not be found"); HandleUndeliveredMessage(im, result); return; } else { //Send the IM, and it made it to the user, return true result(true); return; } } else { //Couldn't find them, stop for now lock (IMUsersCache) { //Remove them so we keep testing against the db IMUsersCache.Remove(toAgentID); } m_log.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message as the region could not be found"); HandleUndeliveredMessage(im, result); } }
/// <summary> /// Recursive 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, ulong prevRegionHandle) { UUID toAgentID = new UUID(im.toAgentID); UserAgentData upd = null; bool lookupAgent = false; lock (m_UserRegionMap) { if (m_UserRegionMap.ContainsKey(toAgentID)) { upd = new UserAgentData(); upd.AgentOnline = true; upd.Handle = 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 (prevRegionHandle == upd.Handle) { lookupAgent = true; } } else { lookupAgent = true; } } // Are we needing to look-up an agent? if (lookupAgent) { // Non-cached user agent lookup. upd = m_Scenes[0].CommsManager.UserService.GetAgentByUUID(toAgentID); if (upd != null) { // check if we've tried this before.. // This is one way to end the recursive loop // if (upd.Handle == prevRegionHandle) { m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } else { m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } if (upd != null) { if (upd.AgentOnline) { RegionInfo reginfo = m_Scenes[0].SceneGridService.RequestNeighbouringRegionInfo(upd.Handle); 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.Handle; } else { m_UserRegionMap.Add(toAgentID, upd.Handle); } } 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 // This is recursive!!!!! SendGridInstantMessageViaXMLRPCAsync(im, result, upd.Handle); } } else { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.Handle); HandleUndeliveredMessage(im, result); } } else { HandleUndeliveredMessage(im, result); } } else { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find user {0}", toAgentID); HandleUndeliveredMessage(im, result); } }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID fromAgentID = new UUID(im.fromAgentID); UUID toAgentID = new UUID(im.toAgentID); foreach (Scene scene in m_Scenes) { if (!scene.EventManager.TriggerOnBeforeSendInstantMessage(im)) { m_log.WarnFormat("[INSTANT MESSAGE]: Outbound IM blocked by module"); return; } // Check for muted senders in specific IM cases. if (m_muteListModule == null) { m_muteListModule = scene.RequestModuleInterface <IMuteListModule>(); } if (m_muteListModule != null) { if ((im.dialog == (int)InstantMessageDialog.MessageFromAgent) || (im.dialog == (int)InstantMessageDialog.MessageFromObject)) { if (m_muteListModule.IsMuted(fromAgentID, toAgentID)) // owner ID is in fromAgentID in case of IMs from objects { return; // recipient has sender muted. } } } } //m_log.DebugFormat("[INSTANT MESSAGE]: Attempting delivery of IM from {0} to {1}", im.fromAgentName, toAgentID.ToString()); // Try root avatar only first foreach (Scene scene in m_Scenes) { if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { //m_log.DebugFormat("[INSTANT MESSAGE]: Looking for {0} in {1}", toAgentID.ToString(), scene.RegionInfo.RegionName); // Local message ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; if (!user.IsChildAgent) { //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); user.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } } // try child avatar second foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { // Local message ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); user.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } if (m_Gridmode) { //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering via grid"); // Still here, try send via Grid SendGridInstantMessageViaXMLRPC(im, result); return; } HandleUndeliveredMessage(im, result); return; }
/// <summary> /// Internal SendGridInstantMessage over XMLRPC method. /// </summary> /// <remarks> /// This is called from within a dedicated thread. /// </remarks> private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); UUID regionID; bool needToLookupAgent; lock (m_UserRegionMap) needToLookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID); while (true) { if (needToLookupAgent) { PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); UUID foundRegionID = UUID.Zero; if (presences != null) { foreach (PresenceInfo p in presences) { if (p.RegionID != UUID.Zero) { foundRegionID = p.RegionID; break; } } } // If not found or the found region is the same as the last lookup, then message is undeliverable if (foundRegionID == UUID.Zero || foundRegionID == regionID) { break; } else { regionID = foundRegionID; } } GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID); if (reginfo == null) { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); break; } // Try to send the message to the agent via the retrieved region. Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); msgdata["region_handle"] = 0; bool imresult = doIMSending(reginfo, msgdata); // If the message delivery was successful, then cache the entry. if (imresult) { lock (m_UserRegionMap) { m_UserRegionMap[toAgentID] = regionID; } result(true); return; } // If we reach this point in the first iteration of the while, then we may have unsuccessfully tried // to use a locally cached region ID. All subsequent attempts need to lookup agent details from // the presence service. needToLookupAgent = true; } // If we reached this point then the message was not deliverable. Remove the bad cache entry and // signal the delivery failure. lock (m_UserRegionMap) m_UserRegionMap.Remove(toAgentID); // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliverableMessage(im, result); }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); if (toAgentID == UUID.Zero) return; IClientAPI client = null; // Try root avatar only first foreach (Scene scene in m_Scenes) { ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null && !sp.IsDeleted && sp.ControllingClient.IsActive) { // actualy don't send via child agents // ims can be complex things, and not sure viewers will not mess up if(sp.IsChildAgent) continue; client = sp.ControllingClient; if(!sp.IsChildAgent) break; } } if(client != null) { // Local message // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); client.SendInstantMessage(im); // Message sent result(true); return; } // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); SendGridInstantMessageViaXMLRPC(im, result); }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); try { // Try root avatar only first m_Scenes.ForEach(delegate(Scene scene) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", // toAgentID.ToString(), scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null && !sp.IsChildAgent) { // Local message // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); throw new ThreadedClasses.ReturnValueException<bool>(true); } }); // try child avatar second m_Scenes.ForEach(delegate(Scene scene) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null) { // Local message // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); throw new ThreadedClasses.ReturnValueException<bool>(true); } }); } catch(ThreadedClasses.ReturnValueException<bool>) { return; } // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); SendGridInstantMessageViaXMLRPC(im, result); }
private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) { lock (pendingInstantMessages) { if (numInstantMessageThreads >= 4) { GIM gim = new GIM(); gim.im = im; gim.result = result; pendingInstantMessages.Enqueue(gim); } else { ++ numInstantMessageThreads; //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads); GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain; d.BeginInvoke(im, result, GridInstantMessageCompleted, d); } } }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = im.toAgentID; // Try root avatar only first - incorrect now, see below foreach (Scene scene in m_Scenes) { IScenePresence user; if (scene.TryGetScenePresence (toAgentID, out user)) { user.ControllingClient.SendInstantMessage (im); return; } } //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); SendGridInstantMessageViaXMLRPC(im, result); }
/// <summary> /// Internal SendGridInstantMessage over XMLRPC method. /// </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> private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result) { GIM gim; do { try { SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero); } catch (Exception e) { m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message); } lock (pendingInstantMessages) { if (pendingInstantMessages.Count > 0) { gim = pendingInstantMessages.Dequeue(); im = gim.im; result = gim.result; } else { gim = null; -- numInstantMessageThreads; //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads); } } } while (gim != null); }
public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); // Try root avatar only first foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}", // toAgentID.ToString(), scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null && !sp.IsChildAgent) { // Local message // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } // try child avatar second foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[HG INSTANT MESSAGE]: Looking for child of {0} in {1}", // toAgentID, scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null) { // Local message // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); // Is the user a local user? string url = string.Empty; bool foreigner = false; if (UserManagementModule != null && !UserManagementModule.IsLocalGridUser(toAgentID)) // foreign user { url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI"); foreigner = true; } Util.FireAndForget(delegate { bool success = false; if (foreigner && url == string.Empty) // we don't know about this user { string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID); m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI); if (recipientUUI != string.Empty) { UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty; if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret)) { success = m_IMService.OutgoingInstantMessage(im, u, true); if (success) { UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last); } } } } else { success = m_IMService.OutgoingInstantMessage(im, url, foreigner); } if (!success && !foreigner) { HandleUndeliveredMessage(im, result); } else { result(success); } }); return; }
private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) { UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; // If this event has handlers, then an IM from an agent will be // considered delivered. This will suppress the error message. // if (handlerUndeliveredMessage != null) { handlerUndeliveredMessage(im); if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) result(true); else result(false); return; } //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable"); result(false); }
public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); // Try root avatar only first - incorrect now, see below foreach (Scene scene in m_Scenes) { if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { // Local message ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; user.ControllingClient.SendInstantMessage(im); return; } } //Note: Why??? This is completely unnesessary! /*// try child avatar second foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { // Local message ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); user.ControllingClient.SendInstantMessage(im); return; } }*/ //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); SendGridInstantMessageViaXMLRPC(im, result); }
/// <summary> /// Recursive 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) { UUID toAgentID = new UUID(im.toAgentID); PresenceInfo upd = null; bool lookupAgent = false; 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; } } // Are we needing to look-up an agent? if (lookupAgent) { // Non-cached user agent lookup. PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) { foreach (PresenceInfo p in presences) { if (p.RegionID != UUID.Zero) { upd = p; break; } } } if (upd != null) { // check if we've tried this before.. // This is one way to end the recursive loop // if (upd.RegionID == prevRegionID) { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } else { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } if (upd != null) { 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 // 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); } }
/// <summary> /// Recursive 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, GridRegion prevRegion) { UUID toAgentID = new UUID(im.toAgentID); PresenceInfo upd = null; GridRegion cachedRegion = null; bool lookupAgent = false; lock (m_UserRegionMap) { if (m_UserRegionMap.ContainsKey(toAgentID)) { //They have been IMed before, look up in the cache upd = new PresenceInfo(); upd.RegionID = m_UserRegionMap[toAgentID].Region.RegionID; cachedRegion = m_UserRegionMap[toAgentID].Region; // 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 (prevRegion != null && prevRegion.RegionID == upd.RegionID) { //If prevRegion is the same as the cache, look them up, someone moved lookupAgent = true; } } else { //Havn't IMed this person before, get their presence info lookupAgent = true; } } // Are we needing to look-up an agent? if (lookupAgent) { //Find the regions http address where the agent is string[] AgentLocations = PresenceService.GetAgentsLocations(new string[] { toAgentID.ToString() }); if (AgentLocations == null || (AgentLocations.Length == 1 && AgentLocations[0] == "Failure")) //If this is true, this doesn't exist on the presence server and we use the legacy way { // Non-cached user agent lookup. PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) upd = presences[0]; if (upd != null) { // check if we've tried this region before.. // This is one way to end the recursive loop if ((upd.RegionID == UUID.Zero) || (prevRegion != null && upd.RegionID == prevRegion.RegionID)) { m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } } else { Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); bool imresult = doIMSending("http://" + cachedRegion.ExternalHostName + ":" + cachedRegion.HttpPort, msgdata); if (imresult) { // IM delivery successful, so store the Agent's location in our local cache. lock (m_UserRegionMap) { m_UserRegionMap[toAgentID] = new IMPresenceInfo(); m_UserRegionMap[toAgentID].HTTPPath = "http://" + cachedRegion.ExternalHostName + ":" + cachedRegion.HttpPort; } result(true); return; } else { // This happens when the agent moves out of the last known region // 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, cachedRegion); } return; //If this isn't here, infinite loop occurs } } if (upd != null) { if(cachedRegion == null) cachedRegion = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID); if (cachedRegion != null) { Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); bool imresult = doIMSending("http://" + cachedRegion.ExternalHostName + ":" + cachedRegion.HttpPort, msgdata); if (imresult) { // IM delivery successful, so store the Agent's location in our local cache. lock (m_UserRegionMap) { m_UserRegionMap[toAgentID] = new IMPresenceInfo(); m_UserRegionMap[toAgentID].Region = cachedRegion; m_UserRegionMap[toAgentID].HTTPPath = "http://" + cachedRegion.ExternalHostName + ":" + cachedRegion.HttpPort; } result(true); } else { // This happens when the agent moves out of the last known region // 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, cachedRegion); } } else { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); HandleUndeliveredMessage(im, result); } } else { HandleUndeliveredMessage(im, result); } }
public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); // Try root avatar only first foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}", // toAgentID.ToString(), scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null && !sp.IsChildAgent) { // Local message // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } // try child avatar second foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( // "[HG INSTANT MESSAGE]: Looking for child of {0} in {1}", // toAgentID, scene.RegionInfo.RegionName); ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null) { // Local message // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); sp.ControllingClient.SendInstantMessage(im); // Message sent result(true); return; } } // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); // Is the user a local user? string url = string.Empty; bool foreigner = false; if (UserManagementModule != null && !UserManagementModule.IsLocalGridUser(toAgentID)) // foreign user { url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI"); foreigner = true; } Util.FireAndForget(delegate { bool success = false; if (foreigner && url == string.Empty) // we don't know about this user { string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID); m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI); if (recipientUUI != string.Empty) { UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty; if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret)) { success = m_IMService.OutgoingInstantMessage(im, u, true); if (success) UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last); } } } else success = m_IMService.OutgoingInstantMessage(im, url, foreigner); if (!success && !foreigner) HandleUndeliveredMessage(im, result); else result(success); }); return; }
/// <summary> /// Recursive 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, GridRegion prevRegion) { UUID toAgentID = new UUID(im.toAgentID); string HTTPPath = ""; Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); lock (IMUsersCache) { if (!IMUsersCache.TryGetValue(toAgentID, out HTTPPath)) HTTPPath = ""; } if (HTTPPath != "") { //We've tried to send an IM to them before, pull out their info //Send the IM to their last location if (!doIMSending(HTTPPath, msgdata)) { //If this fails, the user has either moved from their stored location or logged out //Since it failed, let it look them up again and rerun lock (IMUsersCache) { IMUsersCache.Remove(toAgentID); } //Clear the path and let it continue trying again. HTTPPath = ""; } else { //Send the IM, and it made it to the user, return true result(true); return; } } //Now query the grid server for the agent //Ask for the user new style first string[] AgentLocations = PresenceService.GetAgentsLocations(new string[] { toAgentID.ToString() }); //If this is false, this doesn't exist on the presence server and we use the legacy way if (AgentLocations != null && (AgentLocations.Length != 0 && AgentLocations[0] != "Failure")) { //No agents, so this user is offline if (AgentLocations[0] == "NoAgents") { lock (IMUsersCache) { //Remove them so we keep testing against the db IMUsersCache.Remove(toAgentID); } m_log.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } else //Found the agent, use this location HTTPPath = AgentLocations[0]; } else { //Query the legacy way PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) { Services.Interfaces.GridRegion r = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, presences[0].RegionID); if (r != null) { HTTPPath = "http://" + r.ExternalHostName + ":" + r.HttpPort; } else { //Can't find their region, so stop here lock (IMUsersCache) { //Remove them so we keep testing against the db IMUsersCache.Remove(toAgentID); } m_log.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); result(false); return; } } else { //The user is offline lock (IMUsersCache) { //Remove them so we keep testing against the db IMUsersCache.Remove(toAgentID); } m_log.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } //We found the agent's location, now ask them about the user if (HTTPPath != "") { if (!doIMSending(HTTPPath, msgdata)) { //It failed, stop now lock (IMUsersCache) { //Remove them so we keep testing against the db IMUsersCache.Remove(toAgentID); } m_log.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message as the region could not be found"); result(false); return; } else { //Send the IM, and it made it to the user, return true result(true); return; } } else { //Couldn't find them, stop for now lock (IMUsersCache) { //Remove them so we keep testing against the db IMUsersCache.Remove(toAgentID); } m_log.Info("[GRID INSTANT MESSAGE]: Unable to deliver an instant message as the region could not be found"); result(false); } }
/// <summary> /// Recursive 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) { uint restartloopcount = 100; restart: UUID toAgentID = new UUID(im.toAgentID); PresenceInfo upd = null; UUID _regionID; bool lookupAgent = false; if (m_UserRegionMap.TryGetValue(toAgentID, out _regionID)) { upd = new PresenceInfo(); upd.RegionID = _regionID; // 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; } // Are we needing to look-up an agent? if (lookupAgent) { // Non-cached user agent lookup. PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) { foreach (PresenceInfo p in presences) { if (p.RegionID != UUID.Zero) { upd = p; break; } } } if (upd != null) { // check if we've tried this before.. // This is one way to end the recursive loop // if (upd.RegionID == prevRegionID) { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } else { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } if (upd != null) { 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. m_UserRegionMap[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 // This may end up in an endless loop. However, that is still nicer than the endless recursion that was previously possible. prevRegionID = upd.RegionID; if (restartloopcount-- == 0) { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to locate user after several tries (loop count exceeded)"); HandleUndeliveredMessage(im, result); } goto restart; } } else { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); HandleUndeliveredMessage(im, result); } } else { HandleUndeliveredMessage(im, result); } }
/// <summary> /// Internal SendGridInstantMessage over XMLRPC method. /// </summary> /// <remarks> /// This is called from within a dedicated thread. /// </remarks> private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); UUID regionID; bool needToLookupAgent; lock (m_UserRegionMap) needToLookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID); while (true) { if (needToLookupAgent) { PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); UUID foundRegionID = UUID.Zero; if (presences != null) { foreach (PresenceInfo p in presences) { if (p.RegionID != UUID.Zero) { foundRegionID = p.RegionID; break; } } } // If not found or the found region is the same as the last lookup, then message is undeliverable if (foundRegionID == UUID.Zero || foundRegionID == regionID) break; else regionID = foundRegionID; } GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID); if (reginfo == null) { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); break; } // Try to send the message to the agent via the retrieved region. Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); msgdata["region_handle"] = 0; bool imresult = doIMSending(reginfo, msgdata); // If the message delivery was successful, then cache the entry. if (imresult) { lock (m_UserRegionMap) { m_UserRegionMap[toAgentID] = regionID; } result(true); return; } // If we reach this point in the first iteration of the while, then we may have unsuccessfully tried // to use a locally cached region ID. All subsequent attempts need to lookup agent details from // the presence service. needToLookupAgent = true; } // If we reached this point then the message was not deliverable. Remove the bad cache entry and // signal the delivery failure. lock (m_UserRegionMap) m_UserRegionMap.Remove(toAgentID); // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliverableMessage(im, result); }