From cbd02218704287640ba5c7b564440a6590e038cf Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 23 Nov 2008 05:16:07 +0000 Subject: [PATCH] Plumb in the presence notifications and region shutdown/restart messages from the presence module to the message server, through the user server and on into the database. This should fix the "Already logged in" issue that grids see after a sim crashes, or a user crashes out of a sim. Not yet a 100% solution for friends, but getting there. --- OpenSim/Data/MSSQL/MSSQLUserData.cs | 4 + OpenSim/Data/MySQL/MySQLUserData.cs | 26 ++++++ OpenSim/Data/NHibernate/NHibernateUserData.cs | 4 + OpenSim/Data/SQLite/SQLiteUserData.cs | 4 + OpenSim/Data/UserDataBase.cs | 2 + .../Communications/UserManagerBase.cs | 8 ++ OpenSim/Framework/IUserData.cs | 2 + OpenSim/Grid/MessagingServer/Main.cs | 4 + .../Grid/MessagingServer/MessageService.cs | 77 +++++++++++++-- OpenSim/Grid/UserServer/Main.cs | 29 ++++++ .../UserServer/MessageServersConnector.cs | 93 ++++++++++++++++++- OpenSim/Grid/UserServer/UserManager.cs | 47 ++++++++++ .../Avatar/InstantMessage/PresenceModule.cs | 24 +++-- 13 files changed, 307 insertions(+), 17 deletions(-) diff --git a/OpenSim/Data/MSSQL/MSSQLUserData.cs b/OpenSim/Data/MSSQL/MSSQLUserData.cs index 0afe47cd8e..518565980a 100644 --- a/OpenSim/Data/MSSQL/MSSQLUserData.cs +++ b/OpenSim/Data/MSSQL/MSSQLUserData.cs @@ -732,6 +732,10 @@ namespace OpenSim.Data.MSSQL } } + override public void LogoutUsers(UUID regionID) + { + } + #endregion #region Other public methods diff --git a/OpenSim/Data/MySQL/MySQLUserData.cs b/OpenSim/Data/MySQL/MySQLUserData.cs index 288ca86815..f203a660f6 100644 --- a/OpenSim/Data/MySQL/MySQLUserData.cs +++ b/OpenSim/Data/MySQL/MySQLUserData.cs @@ -891,5 +891,31 @@ namespace OpenSim.Data.MySQL dbm.Release(); } } + + public override void LogoutUsers(UUID regionID) + { + Dictionary param = new Dictionary(); + param["?regionID"] = regionID.ToString(); + + MySQLSuperManager dbm = GetLockedConnection("LogoutUsers"); + + try + { + dbm.Manager.ExecuteParameterizedSql( + "update " + m_agentsTableName + " SET agentOnline = 0 " + + "where currentRegion = ?regionID", + param); + } + catch (Exception e) + { + dbm.Manager.Reconnect(); + m_log.Error(e.ToString()); + return; + } + finally + { + dbm.Release(); + } + } } } diff --git a/OpenSim/Data/NHibernate/NHibernateUserData.cs b/OpenSim/Data/NHibernate/NHibernateUserData.cs index 5ef48c8784..1bb2b14d73 100644 --- a/OpenSim/Data/NHibernate/NHibernateUserData.cs +++ b/OpenSim/Data/NHibernate/NHibernateUserData.cs @@ -308,6 +308,10 @@ namespace OpenSim.Data.NHibernate { } + public override void LogoutUsers(UUID regionID) + { + } + public override string Name { get { return "NHibernate"; } } diff --git a/OpenSim/Data/SQLite/SQLiteUserData.cs b/OpenSim/Data/SQLite/SQLiteUserData.cs index 369fc51460..b8f1a6830a 100644 --- a/OpenSim/Data/SQLite/SQLiteUserData.cs +++ b/OpenSim/Data/SQLite/SQLiteUserData.cs @@ -1037,5 +1037,9 @@ namespace OpenSim.Data.SQLite override public void ResetAttachments(UUID userID) { } + + override public void LogoutUsers(UUID regionID) + { + } } } diff --git a/OpenSim/Data/UserDataBase.cs b/OpenSim/Data/UserDataBase.cs index a5fc8c874a..c1b320baee 100644 --- a/OpenSim/Data/UserDataBase.cs +++ b/OpenSim/Data/UserDataBase.cs @@ -75,6 +75,8 @@ namespace OpenSim.Data // } public abstract void ResetAttachments(UUID userID); + public abstract void LogoutUsers(UUID regionID); + public abstract string Version {get;} public abstract string Name {get;} public abstract void Initialise(string connect); diff --git a/OpenSim/Framework/Communications/UserManagerBase.cs b/OpenSim/Framework/Communications/UserManagerBase.cs index bc1a593cc0..46b28d73b0 100644 --- a/OpenSim/Framework/Communications/UserManagerBase.cs +++ b/OpenSim/Framework/Communications/UserManagerBase.cs @@ -87,6 +87,14 @@ namespace OpenSim.Framework.Communications return null; } + public void LogoutUsers(UUID regionID) + { + foreach (IUserDataPlugin plugin in _plugins) + { + plugin.LogoutUsers(regionID); + } + } + public void ResetAttachments(UUID userID) { foreach (IUserDataPlugin plugin in _plugins) diff --git a/OpenSim/Framework/IUserData.cs b/OpenSim/Framework/IUserData.cs index 07159cc51a..0936495ff1 100644 --- a/OpenSim/Framework/IUserData.cs +++ b/OpenSim/Framework/IUserData.cs @@ -177,6 +177,8 @@ namespace OpenSim.Framework void UpdateUserAppearance(UUID user, AvatarAppearance appearance); void ResetAttachments(UUID userID); + + void LogoutUsers(UUID regionID); } public class UserDataInitialiser : PluginInitialiserBase diff --git a/OpenSim/Grid/MessagingServer/Main.cs b/OpenSim/Grid/MessagingServer/Main.cs index 84725716f8..5568f73c64 100644 --- a/OpenSim/Grid/MessagingServer/Main.cs +++ b/OpenSim/Grid/MessagingServer/Main.cs @@ -88,6 +88,10 @@ namespace OpenSim.Grid.MessagingServer m_httpServer.AddXmlRPCHandler("login_to_simulator", msgsvc.UserLoggedOn); m_httpServer.AddXmlRPCHandler("logout_of_simulator", msgsvc.UserLoggedOff); m_httpServer.AddXmlRPCHandler("get_presence_info_bulk", msgsvc.GetPresenceInfoBulk); + m_httpServer.AddXmlRPCHandler("region_startup", msgsvc.RegionStartup); + m_httpServer.AddXmlRPCHandler("region_shutdown", msgsvc.RegionShutdown); + m_httpServer.AddXmlRPCHandler("agent_location", msgsvc.AgentLocation); + m_httpServer.AddXmlRPCHandler("agent_leaving", msgsvc.AgentLeaving); m_httpServer.Start(); m_log.Info("[SERVER]: Userserver registration was successful"); diff --git a/OpenSim/Grid/MessagingServer/MessageService.cs b/OpenSim/Grid/MessagingServer/MessageService.cs index 66916b6c1c..a4e54c7918 100644 --- a/OpenSim/Grid/MessagingServer/MessageService.cs +++ b/OpenSim/Grid/MessagingServer/MessageService.cs @@ -558,24 +558,30 @@ namespace OpenSim.Grid.MessagingServer public bool deregisterWithUserServer() { - Hashtable UserParams = new Hashtable(); + Hashtable request = new Hashtable(); + + return SendToUserServer(request, "deregister_messageserver"); + } + + public bool SendToUserServer(Hashtable request, string method) + { // Login / Authentication if (m_cfg.HttpSSL) { - UserParams["uri"] = "https://" + m_cfg.MessageServerIP + ":" + m_cfg.HttpPort; + request["uri"] = "https://" + m_cfg.MessageServerIP + ":" + m_cfg.HttpPort; } else { - UserParams["uri"] = "http://" + m_cfg.MessageServerIP + ":" + m_cfg.HttpPort; + request["uri"] = "http://" + m_cfg.MessageServerIP + ":" + m_cfg.HttpPort; } - UserParams["recvkey"] = m_cfg.UserRecvKey; - UserParams["sendkey"] = m_cfg.UserRecvKey; + request["recvkey"] = m_cfg.UserRecvKey; + request["sendkey"] = m_cfg.UserRecvKey; // Package into an XMLRPC Request ArrayList SendParams = new ArrayList(); - SendParams.Add(UserParams); + SendParams.Add(request); bool success = true; string[] servers = m_cfg.UserServerURL.Split(' '); @@ -585,7 +591,7 @@ namespace OpenSim.Grid.MessagingServer { try { - XmlRpcRequest UserReq = new XmlRpcRequest("deregister_messageserver", SendParams); + XmlRpcRequest UserReq = new XmlRpcRequest(method, SendParams); XmlRpcResponse UserResp = UserReq.Send(m_cfg.UserServerURL, 16000); // Process Response Hashtable UserRespData = (Hashtable)UserResp.Value; @@ -603,5 +609,62 @@ namespace OpenSim.Grid.MessagingServer } #endregion + + public XmlRpcResponse RegionStartup(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable result = new Hashtable(); + result["success"] = "FALSE"; + + if(SendToUserServer(requestData, "region_startup")) + result["success"] = "TRUE"; + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = result; + return response; + } + + public XmlRpcResponse RegionShutdown(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable result = new Hashtable(); + result["success"] = "FALSE"; + + if(SendToUserServer(requestData, "region_shutdown")) + result["success"] = "TRUE"; + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = result; + return response; + } + + public XmlRpcResponse AgentLocation(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable result = new Hashtable(); + result["success"] = "FALSE"; + + if(SendToUserServer(requestData, "agent_location")) + result["success"] = "TRUE"; + + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = result; + return response; + } + + public XmlRpcResponse AgentLeaving(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable result = new Hashtable(); + result["success"] = "FALSE"; + + if(SendToUserServer(requestData, "agent_leaving")) + result["success"] = "TRUE"; + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = result; + return response; + } } } diff --git a/OpenSim/Grid/UserServer/Main.cs b/OpenSim/Grid/UserServer/Main.cs index eb47259ffe..f894ca0672 100644 --- a/OpenSim/Grid/UserServer/Main.cs +++ b/OpenSim/Grid/UserServer/Main.cs @@ -110,6 +110,11 @@ namespace OpenSim.Grid.UserServer m_loginService.OnUserLoggedInAtLocation += NotifyMessageServersUserLoggedInToLocation; m_userManager.OnLogOffUser += NotifyMessageServersUserLoggOff; + m_messagesService.OnAgentLocation += HandleAgentLocation; + m_messagesService.OnAgentLeaving += HandleAgentLeaving; + m_messagesService.OnRegionStartup += HandleRegionStartup; + m_messagesService.OnRegionShutdown += HandleRegionShutdown; + m_log.Info("[REGION]: Starting HTTP process"); m_httpServer = new BaseHttpServer(Cfg.HttpPort); @@ -147,6 +152,10 @@ namespace OpenSim.Grid.UserServer m_httpServer.AddXmlRPCHandler("get_agent_by_uuid", m_userManager.XmlRPCGetAgentMethodUUID); m_httpServer.AddXmlRPCHandler("check_auth_session", m_userManager.XmlRPCCheckAuthSession); m_httpServer.AddXmlRPCHandler("set_login_params", m_loginService.XmlRPCSetLoginParams); + m_httpServer.AddXmlRPCHandler("region_startup", m_messagesService.RegionStartup); + m_httpServer.AddXmlRPCHandler("region_shutdown", m_messagesService.RegionShutdown); + m_httpServer.AddXmlRPCHandler("agent_location", m_messagesService.AgentLocation); + m_httpServer.AddXmlRPCHandler("agent_leaving", m_messagesService.AgentLeaving); // Message Server ---> User Server m_httpServer.AddXmlRPCHandler("register_messageserver", m_messagesService.XmlRPCRegisterMessageServer); m_httpServer.AddXmlRPCHandler("agent_change_region", m_messagesService.XmlRPCUserMovedtoRegion); @@ -442,5 +451,25 @@ namespace OpenSim.Grid.UserServer m_messagesService.TellMessageServersAboutUser(agentID, sessionID, RegionID, regionhandle, positionX, positionY, positionZ, firstname, lastname); } + + public void HandleAgentLocation(UUID agentID, UUID regionID, ulong regionHandle) + { + m_userManager.HandleAgentLocation(agentID, regionID, regionHandle); + } + + public void HandleAgentLeaving(UUID agentID, UUID regionID, ulong regionHandle) + { + m_userManager.HandleAgentLeaving(agentID, regionID, regionHandle); + } + + public void HandleRegionStartup(UUID regionID) + { + m_userManager.HandleRegionStartup(regionID); + } + + public void HandleRegionShutdown(UUID regionID) + { + m_userManager.HandleRegionShutdown(regionID); + } } } diff --git a/OpenSim/Grid/UserServer/MessageServersConnector.cs b/OpenSim/Grid/UserServer/MessageServersConnector.cs index 61f125e207..66596173f0 100644 --- a/OpenSim/Grid/UserServer/MessageServersConnector.cs +++ b/OpenSim/Grid/UserServer/MessageServersConnector.cs @@ -57,7 +57,13 @@ namespace OpenSim.Grid.UserServer public float positionZ; public string firstname; public string lastname; - }; + } + + public delegate void AgentLocationDelegate(UUID agentID, UUID regionID, ulong regionHandle); + public delegate void AgentLeavingDelegate(UUID agentID, UUID regionID, ulong regionHandle); + public delegate void RegionStartupDelegate(UUID regionID); + public delegate void RegionShutdownDelegate(UUID regionID); + public class MessageServersConnector { @@ -70,6 +76,11 @@ namespace OpenSim.Grid.UserServer Thread m_NotifyThread; + public event AgentLocationDelegate OnAgentLocation; + public event AgentLeavingDelegate OnAgentLeaving; + public event RegionStartupDelegate OnRegionStartup; + public event RegionShutdownDelegate OnRegionShutdown; + public MessageServersConnector() { MessageServers = new Dictionary(); @@ -337,5 +348,85 @@ namespace OpenSim.Grid.UserServer } } } + + public XmlRpcResponse RegionStartup(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable result = new Hashtable(); + + UUID regionID; + if (UUID.TryParse((string)requestData["RegionUUID"], out regionID)) + { + if (OnRegionStartup != null) + OnRegionStartup(regionID); + + result["responsestring"] = "TRUE"; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = result; + return response; + } + + public XmlRpcResponse RegionShutdown(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable result = new Hashtable(); + + UUID regionID; + if (UUID.TryParse((string)requestData["RegionUUID"], out regionID)) + { + if (OnRegionShutdown != null) + OnRegionShutdown(regionID); + + result["responsestring"] = "TRUE"; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = result; + return response; + } + + public XmlRpcResponse AgentLocation(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable result = new Hashtable(); + + UUID agentID; + UUID regionID; + ulong regionHandle; + if (UUID.TryParse((string)requestData["AgentID"], out agentID) && UUID.TryParse((string)requestData["RegionUUID"], out regionID) && ulong.TryParse((string)requestData["RegionHandle"], out regionHandle)) + { + if (OnAgentLocation != null) + OnAgentLocation(agentID, regionID, regionHandle); + + result["responsestring"] = "TRUE"; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = result; + return response; + } + + public XmlRpcResponse AgentLeaving(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable result = new Hashtable(); + + UUID agentID; + UUID regionID; + ulong regionHandle; + if (UUID.TryParse((string)requestData["AgentID"], out agentID) && UUID.TryParse((string)requestData["RegionUUID"], out regionID) && ulong.TryParse((string)requestData["RegionHandle"], out regionHandle)) + { + if (OnAgentLeaving != null) + OnAgentLeaving(agentID, regionID, regionHandle); + + result["responsestring"] = "TRUE"; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = result; + return response; + } } } diff --git a/OpenSim/Grid/UserServer/UserManager.cs b/OpenSim/Grid/UserServer/UserManager.cs index f7e4e3c69b..04510b2b5a 100644 --- a/OpenSim/Grid/UserServer/UserManager.cs +++ b/OpenSim/Grid/UserServer/UserManager.cs @@ -758,5 +758,52 @@ namespace OpenSim.Grid.UserServer { throw new Exception("The method or operation is not implemented."); } + + public void HandleAgentLocation(UUID agentID, UUID regionID, ulong regionHandle) + { + UserProfileData userProfile = GetUserProfile(agentID); + if (userProfile != null) + { + userProfile.CurrentAgent.Region = regionID; + userProfile.CurrentAgent.Handle = regionHandle; + CommitAgent(ref userProfile); + } + } + + public void HandleAgentLeaving(UUID agentID, UUID regionID, ulong regionHandle) + { + UserProfileData userProfile = GetUserProfile(agentID); + if (userProfile != null) + { + if (userProfile.CurrentAgent.Region == regionID) + { + UserAgentData userAgent = userProfile.CurrentAgent; + if (userAgent != null && userAgent.AgentOnline) + { + userAgent.AgentOnline = false; + userAgent.LogoutTime = Util.UnixTimeSinceEpoch(); + if (regionID != UUID.Zero) + { + userAgent.Region = regionID; + } + userAgent.Handle = regionHandle; + userProfile.LastLogin = userAgent.LogoutTime; + + CommitAgent(ref userProfile); + } + } + } + } + + public void HandleRegionStartup(UUID regionID) + { + LogoutUsers(regionID); + } + + public void HandleRegionShutdown(UUID regionID) + { + LogoutUsers(regionID); + } + } } diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs index aa1db1d8b3..7b358c27f5 100644 --- a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs @@ -114,10 +114,14 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage public void OnNewClient(IClientAPI client) { client.OnConnectionClosed += OnConnectionClosed; + client.OnLogout += OnConnectionClosed; } public void OnConnectionClosed(IClientAPI client) { + if (!(client.Scene is Scene)) + return; + if (!(m_RootAgents.ContainsKey(client.AgentId))) return; @@ -128,7 +132,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage m_RootAgents.Remove(client.AgentId); - NotifyMessageServerOfAgentLeaving(client.AgentId, scene.RegionInfo.RegionName); + NotifyMessageServerOfAgentLeaving(client.AgentId, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle); } public void OnSetRootAgentScene(UUID agentID, Scene scene) @@ -139,13 +143,13 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage return; } m_RootAgents[agentID] = scene; - NotifyMessageServerOfAgentLocation(agentID, scene.RegionInfo.RegionName); + NotifyMessageServerOfAgentLocation(agentID, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle); } private void NotifyMessageServerOfStartup(Scene scene) { Hashtable xmlrpcdata = new Hashtable(); - xmlrpcdata["RegionName"] = scene.RegionInfo.RegionName; + xmlrpcdata["RegionUUID"] = scene.RegionInfo.RegionID.ToString(); ArrayList SendParams = new ArrayList(); SendParams.Add(xmlrpcdata); try @@ -154,7 +158,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage XmlRpcResponse resp = UpRequest.Send(scene.CommsManager.NetworkServersInfo.MessagingURL, 5000); Hashtable responseData = (Hashtable)resp.Value; - if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE") + if (responseData == null || (!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE") { m_log.ErrorFormat("[PRESENCE] Failed to notify message server of region startup for region {0}", scene.RegionInfo.RegionName); } @@ -168,7 +172,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage private void NotifyMessageServerOfShutdown(Scene scene) { Hashtable xmlrpcdata = new Hashtable(); - xmlrpcdata["RegionName"] = scene.RegionInfo.RegionName; + xmlrpcdata["RegionUUID"] = scene.RegionInfo.RegionID.ToString(); ArrayList SendParams = new ArrayList(); SendParams.Add(xmlrpcdata); try @@ -188,11 +192,12 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage } } - private void NotifyMessageServerOfAgentLocation(UUID agentID, string region) + private void NotifyMessageServerOfAgentLocation(UUID agentID, UUID region, ulong regionHandle) { Hashtable xmlrpcdata = new Hashtable(); xmlrpcdata["AgentID"] = agentID.ToString(); - xmlrpcdata["RegionName"] = region; + xmlrpcdata["RegionUUID"] = region.ToString(); + xmlrpcdata["RegionHandle"] = regionHandle.ToString(); ArrayList SendParams = new ArrayList(); SendParams.Add(xmlrpcdata); try @@ -212,11 +217,12 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage } } - private void NotifyMessageServerOfAgentLeaving(UUID agentID, string region) + private void NotifyMessageServerOfAgentLeaving(UUID agentID, UUID region, ulong regionHandle) { Hashtable xmlrpcdata = new Hashtable(); xmlrpcdata["AgentID"] = agentID.ToString(); - xmlrpcdata["RegionName"] = region; + xmlrpcdata["RegionUUID"] = region.ToString(); + xmlrpcdata["RegionHandle"] = regionHandle.ToString(); ArrayList SendParams = new ArrayList(); SendParams.Add(xmlrpcdata); try