* Implements UserServer logoff in a few situations

* User tries to log-in but is already logged in.  Userserver will send message to simulator user was in to log the user out there.
* From the UserServer, admin types 'logoff-user firstname lastname message'.
* Some regions may not get the message because they're not updated yet.
0.6.0-stable
Teravus Ovares 2008-05-31 12:18:29 +00:00
parent f2f183b307
commit febe78d062
21 changed files with 344 additions and 17 deletions

View File

@ -321,9 +321,9 @@ namespace OpenSim.Data.MSSQL
#endregion
override public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid)
override public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid, ulong regionhandle)
{
m_log.Info("[USER]: Stub UpdateUserCUrrentRegion called");
//m_log.Info("[USER]: Stub UpdateUserCUrrentRegion called");
}

View File

@ -382,9 +382,9 @@ namespace OpenSim.Data.MySQL
#endregion
override public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid)
override public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid, ulong regionhandle)
{
m_log.Info("[USER DB]: Stub UpdateUserCUrrentRegion called");
//m_log.Info("[USER DB]: Stub UpdateUserCUrrentRegion called");
}
override public List<AvatarPickerAvatar> GeneratePickerResults(LLUUID queryID, string query)

View File

@ -295,7 +295,7 @@ namespace OpenSim.Data.NHibernate
}
// TODO: actually implement these
public override void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid) {return;}
public override void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid, ulong regionhandle) { return; }
public override void StoreWebLoginKey(LLUUID agentID, LLUUID webLoginKey) {return;}
public override void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms) {return;}
public override void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend) {return;}

View File

@ -238,9 +238,9 @@ namespace OpenSim.Data.SQLite
#endregion
override public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid)
override public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid, ulong regionhandle)
{
m_log.Info("[USER DB]: Stub UpdateUserCUrrentRegion called");
//m_log.Info("[USER DB]: Stub UpdateUserCUrrentRegion called");
}

View File

@ -47,7 +47,7 @@ namespace OpenSim.Data
public abstract void StoreWebLoginKey(LLUUID agentID, LLUUID webLoginKey);
public abstract void AddNewUserProfile(UserProfileData user);
public abstract bool UpdateUserProfile(UserProfileData user);
public abstract void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid);
public abstract void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid, ulong regionhandle);
public abstract void AddNewUserAgent(UserAgentData agent);
public abstract void AddNewUserFriend(LLUUID friendlistowner, LLUUID friend, uint perms);
public abstract void RemoveUserFriend(LLUUID friendlistowner, LLUUID friend);

View File

@ -113,6 +113,13 @@ namespace OpenSim.Framework.Communications
/// Get's the User Appearance
AvatarAppearance GetUserAppearance(LLUUID user);
/// <summary>
/// Updates the current region the User is in
/// </summary>
/// <param name="avatarid">User Region the Avatar is IN</param>
/// <param name="retionuuid">User Region the Avatar is IN</param>
void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid, ulong regionhandle);
void UpdateUserAppearance(LLUUID user, AvatarAppearance appearance);
void AddAttachment(LLUUID user, LLUUID attach);

View File

@ -79,7 +79,15 @@ namespace OpenSim.Framework.Communications
/// <param name="response">The existing response</param>
/// <param name="theUser">The user profile</param>
public abstract void CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest);
/// <summary>
/// If the user is already logged in, try to notify the region that the user they've got is dead.
/// </summary>
/// <param name="theUser"></param>
public virtual void LogOffUser(UserProfileData theUser, string message)
{
}
/// <summary>
/// Get the initial login inventory skeleton (in other words, the folder structure) for the given user.
/// </summary>
@ -196,9 +204,14 @@ namespace OpenSim.Framework.Communications
// because of some problem, for instance, the crashment of server or client,
// the user cannot log in any longer.
userProfile.CurrentAgent.AgentOnline = false;
m_userManager.CommitAgent(ref userProfile);
m_userManager.CommitAgent(ref userProfile);
// try to tell the region that their user is dead.
LogOffUser(userProfile, "You were logged off because you logged in from another location");
// Reject the login
m_log.InfoFormat(
"[LOGIN END]: Notifying user {0} {1} that they are already logged in",

View File

@ -187,6 +187,21 @@ namespace OpenSim.Framework.Communications
return null;
}
public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid, ulong regionhandle)
{
foreach (KeyValuePair<string, IUserData> plugin in _plugins)
{
try
{
plugin.Value.UpdateUserCurrentRegion(avatarid, regionuuid, regionhandle);
}
catch (Exception e)
{
m_log.Info("[USERSTORAGE]: Unable to updateuser location via " + plugin.Key + "(" + e.ToString() + ")");
}
}
}
/// <summary>
/// Loads a user's friend list
/// </summary>

View File

@ -50,6 +50,8 @@ namespace OpenSim.Framework
public delegate bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData);
public delegate void LogOffUser(ulong regionHandle, LLUUID agentID, LLUUID regionSecret, string message);
public interface IRegionCommsListener
{
event ExpectUserDelegate OnExpectUser;
@ -63,5 +65,6 @@ namespace OpenSim.Framework
event CloseAgentConnection OnCloseAgentConnection;
event RegionUp OnRegionUp;
event ChildAgentUpdate OnChildAgentUpdate;
event LogOffUser OnLogOffUser;
}
}

View File

@ -98,13 +98,8 @@ namespace OpenSim.Framework
/// <param name="user">UserProfile to update</param>
bool UpdateUserProfile(UserProfileData user);
/// <summary>
/// Updates the current region the User is in
/// </summary>
/// <param name="avatarid">User Region the Avatar is IN</param>
/// <param name="retionuuid">User Region the Avatar is IN</param>
void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid);
void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid, ulong regionhandle);
/// <summary>
/// Adds a new agent to the database
/// </summary>

View File

@ -45,6 +45,7 @@ namespace OpenSim.Framework
private UpdateNeighbours handlerNeighboursUpdate = null; // OnNeighboursUpdate;
private PrimCrossing handlerPrimCrossingIntoRegion = null; // OnPrimCrossingIntoRegion;
private RegionUp handlerRegionUp = null; // OnRegionUp;
private LogOffUser handlerLogOffUser = null;
#region IRegionCommsListener Members
@ -59,6 +60,7 @@ namespace OpenSim.Framework
public event CloseAgentConnection OnCloseAgentConnection;
public event RegionUp OnRegionUp;
public event ChildAgentUpdate OnChildAgentUpdate;
public event LogOffUser OnLogOffUser;
#endregion
@ -79,6 +81,17 @@ namespace OpenSim.Framework
return false;
}
// From User Server
public virtual void TriggerLogOffUser(ulong regionHandle, LLUUID agentID, LLUUID RegionSecret, string message)
{
handlerLogOffUser = OnLogOffUser;
if (handlerLogOffUser != null)
{
handlerLogOffUser(regionHandle, agentID, RegionSecret, message);
}
}
public virtual bool TriggerExpectPrim(ulong regionHandle, LLUUID primID, string objData, int XMLMethod)
{

View File

@ -84,6 +84,7 @@ namespace OpenSim.Framework.Servers
Notice("show uptime - show server startup and uptime.");
Notice("shutdown - shutdown the server.\n");
break;
case "show":

View File

@ -129,6 +129,7 @@ namespace OpenSim.Grid.UserServer
m_httpServer.AddXmlRPCHandler("get_user_friend_list", m_userManager.XmlRpcResponseXmlRPCGetUserFriendList);
m_httpServer.AddXmlRPCHandler("get_avatar_appearance", m_userManager.XmlRPCGetAvatarAppearance);
m_httpServer.AddXmlRPCHandler("update_avatar_appearance", m_userManager.XmlRPCUpdateAvatarAppearance);
m_httpServer.AddXmlRPCHandler("update_user_current_region", m_userManager.XmlRPCAtRegion);
m_httpServer.AddXmlRPCHandler("logout_of_simulator", m_userManager.XmlRPCLogOffUserMethodUUID);
// Message Server ---> User Server
@ -221,6 +222,7 @@ namespace OpenSim.Grid.UserServer
{
case "help":
m_console.Notice("create user - create a new user");
m_console.Notice("logoff-user <firstname> <lastname> <message> - logs off the specified user from the grid");
break;
case "create":
@ -238,6 +240,67 @@ namespace OpenSim.Grid.UserServer
"RootFolders/",
m_lastCreatedUser);
break;
case "logoff-user":
if (cmdparams.Length >= 3)
{
string firstname = cmdparams[0];
string lastname = cmdparams[1];
string message = "";
for (int i = 2; i < cmdparams.Length; i++)
message += " " + cmdparams[i];
UserProfileData theUser = null;
try
{
theUser = m_loginService.GetTheUser(firstname, lastname);
}
catch (Exception)
{
m_log.Error("[LOGOFF]: Error getting user data from the database.");
}
if (theUser != null)
{
if (theUser.CurrentAgent != null)
{
if (theUser.CurrentAgent.AgentOnline)
{
m_log.Info("[LOGOFF]: Logging off requested user!");
m_loginService.LogOffUser(theUser, message);
theUser.CurrentAgent.AgentOnline = false;
m_loginService.CommitAgent(ref theUser);
}
else
{
m_log.Info("[LOGOFF]: User Doesn't appear to be online, sending the logoff message anyway.");
m_loginService.LogOffUser(theUser, message);
theUser.CurrentAgent.AgentOnline = false;
m_loginService.CommitAgent(ref theUser);
}
}
else
{
m_log.Error("[LOGOFF]: Unable to logoff-user. User doesn't have an agent record so I can't find the simulator to notify");
}
}
else
{
m_log.Info("[LOGOFF]: User doesn't exist in the database");
}
}
else
{
m_log.Error("[LOGOFF]: Invalid amount of parameters. logoff-user takes at least three. Firstname, Lastname, and message");
}
break;
}
}

View File

@ -60,6 +60,65 @@ namespace OpenSim.Grid.UserServer
{
m_config = config;
}
public override void LogOffUser(UserProfileData theUser, string message)
{
RegionProfileData SimInfo = null;
try
{
SimInfo = RegionProfileData.RequestSimProfileData(
theUser.CurrentAgent.Handle, m_config.GridServerURL,
m_config.GridSendKey, m_config.GridRecvKey);
if (SimInfo == null)
{
m_log.Error("[GRID]: Region user was in isn't currently logged in");
return;
}
}
catch (Exception)
{
m_log.Error("[GRID]: Unable to look up region to log user off");
return;
}
// Prepare notification
Hashtable SimParams = new Hashtable();
SimParams["agent_id"] = theUser.ID.ToString();
SimParams["region_secret"] = theUser.CurrentAgent.SecureSessionID.ToString();
//SimParams["region_secret"] = SimInfo.regionSecret;
//m_log.Info(SimInfo.regionSecret);
SimParams["regionhandle"] = theUser.CurrentAgent.Handle.ToString();
SimParams["message"] = message;
ArrayList SendParams = new ArrayList();
SendParams.Add(SimParams);
// Update agent with target sim
m_log.InfoFormat(
"[ASSUMED CRASH]: Telling region {0} @ {1},{2} ({3}) that their agent is dead: {4}",
SimInfo.regionName, SimInfo.regionLocX, SimInfo.regionLocY, SimInfo.httpServerURI, theUser.FirstName + " " + theUser.SurName);
try
{
XmlRpcRequest GridReq = new XmlRpcRequest("logoff_user", SendParams);
XmlRpcResponse GridResp = GridReq.Send(SimInfo.httpServerURI, 6000);
if (GridResp.IsFault)
{
m_log.ErrorFormat(
"[LOGIN]: XMLRPC request for {0} failed, fault code: {1}, reason: {2}, This is likely an old region revision.",
SimInfo.httpServerURI, GridResp.FaultCode, GridResp.FaultString);
}
}
catch (Exception)
{
m_log.Error("[LOGIN]: Error telling region to logout user!");
}
//base.LogOffUser(theUser);
}
//public override void LogOffUser(UserProfileData theUser)
//{
//}
/// <summary>
/// Customises the login response and fills in missing values.

View File

@ -179,6 +179,54 @@ namespace OpenSim.Grid.UserServer
return AvatarPickerListtoXmlRPCResponse(queryID, returnAvatar);
}
public XmlRpcResponse XmlRPCAtRegion(XmlRpcRequest request)
{
XmlRpcResponse response = new XmlRpcResponse();
Hashtable requestData = (Hashtable)request.Params[0];
Hashtable responseData = new Hashtable();
string returnstring = "FALSE";
if (requestData.Contains("avatar_id") && requestData.Contains("region_handle") && requestData.Contains("region_uuid"))
{
ulong cregionhandle = 0;
LLUUID regionUUID = LLUUID.Zero;
LLUUID AvatarID = LLUUID.Zero;
Helpers.TryParse((string)requestData["avatar_id"], out AvatarID);
Helpers.TryParse((string)requestData["region_uuid"], out regionUUID);
try
{
cregionhandle = (ulong)Convert.ToInt64((string)requestData["region_handle"]);
}
catch (ArgumentException)
{
}
catch (OverflowException)
{
}
catch (FormatException)
{
}
if (AvatarID != LLUUID.Zero)
{
UserProfileData userProfile = GetUserProfile(new LLUUID((string)requestData["avatar_id"]));
userProfile.CurrentAgent.Region = new LLUUID((string)requestData["region_uuid"]);
userProfile.CurrentAgent.Handle = (ulong)Convert.ToInt64((string)requestData["region_handle"]);
//userProfile.CurrentAgent.
CommitAgent(ref userProfile);
//setUserProfile(userProfile);
returnstring = "TRUE";
}
}
responseData.Add("returnString", returnstring);
response.Value = responseData;
return response;
}
public XmlRpcResponse XmlRpcResponseXmlRPCAddUserFriend(XmlRpcRequest request)
{
XmlRpcResponse response = new XmlRpcResponse();

View File

@ -419,6 +419,16 @@ namespace OpenSim.Region.Communications.Local
}
}
public void TriggerLogOffUser(ulong regionHandle, LLUUID agentID, LLUUID RegionSecret, string message)
{
if (m_regionListeners.ContainsKey(regionHandle))
{
//m_log.Info("[INTER]: " + rdebugRegionName + ":Local BackEnd: FoundLocalRegion To send it to: " + agent.firstname + " " + agent.lastname);
m_regionListeners[regionHandle].TriggerLogOffUser(regionHandle, agentID, RegionSecret, message);
}
}
public void TriggerExpectPrim(ulong regionHandle, LLUUID primID, string objData, int XMLMethod)
{
if (m_regionListeners.ContainsKey(regionHandle))

View File

@ -86,6 +86,7 @@ namespace OpenSim.Region.Communications.OGS1
httpServer = httpServe;
//Respond to Grid Services requests
httpServer.AddXmlRPCHandler("expect_user", ExpectUser);
httpServer.AddXmlRPCHandler("logoff_user", LogOffUser);
httpServer.AddXmlRPCHandler("check", PingCheckReply);
StartRemoting();
@ -601,6 +602,31 @@ namespace OpenSim.Region.Communications.OGS1
m_log.Info("[OGS1 GRID SERVICES]: Welcoming new user...");
return new XmlRpcResponse();
}
// Grid Request Processing
/// <summary>
/// Ooops, our Agent must be dead if we're getting this request!
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public XmlRpcResponse LogOffUser(XmlRpcRequest request)
{
m_log.Debug("[CONNECTION DEBUGGING]: LogOff User Called ");
Hashtable requestData = (Hashtable)request.Params[0];
string message = (string)requestData["message"];
LLUUID agentID = LLUUID.Zero;
LLUUID RegionSecret = LLUUID.Zero;
Helpers.TryParse((string)requestData["agent_id"], out agentID);
Helpers.TryParse((string)requestData["region_secret"], out RegionSecret);
ulong regionHandle = Convert.ToUInt64((string)requestData["regionhandle"]);
m_localBackend.TriggerLogOffUser(regionHandle, agentID, RegionSecret,message);
return new XmlRpcResponse();
}

View File

@ -196,6 +196,36 @@ namespace OpenSim.Region.Communications.OGS1
return GetUserProfile(firstName + " " + lastName);
}
public void UpdateUserCurrentRegion(LLUUID avatarid, LLUUID regionuuid, ulong regionhandle)
{
Hashtable param = new Hashtable();
param.Add("avatar_id", avatarid.ToString());
param.Add("region_uuid", regionuuid.ToString());
param.Add("region_handle", regionhandle.ToString());
IList parameters = new ArrayList();
parameters.Add(param);
XmlRpcRequest req = new XmlRpcRequest("update_user_current_region", parameters);
XmlRpcResponse resp = req.Send(m_parent.NetworkServersInfo.UserURL, 3000);
Hashtable respData = (Hashtable)resp.Value;
if (respData.ContainsKey("returnString"))
{
if ((string)respData["returnString"] == "TRUE")
{
m_log.Info("[OSG1 USER SERVICES]: Successfully updated user record");
}
else
{
m_log.Error("[OSG1 USER SERVICES]: Error updating user record");
}
}
else
{
m_log.Warn("[OSG1 USER SERVICES]: Error updating user record, Grid server may not be updated.");
}
}
public List<AvatarPickerAvatar> GenerateAgentPickerRequestResponse(LLUUID queryID, string query)
{
List<AvatarPickerAvatar> pickerlist = new List<AvatarPickerAvatar>();

View File

@ -2003,8 +2003,8 @@ namespace OpenSim.Region.Environment.Scenes
m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
m_sceneGridService.OnExpectPrim += IncomingInterRegionPrimGroup;
m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
m_sceneGridService.KillObject = SendKillObject;
m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
m_sceneGridService.KillObject += SendKillObject;
}
/// <summary>
@ -2012,6 +2012,8 @@ namespace OpenSim.Region.Environment.Scenes
/// </summary>
public void UnRegisterReginWithComms()
{
m_sceneGridService.KillObject -= SendKillObject;
m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
m_sceneGridService.OnExpectPrim -= IncomingInterRegionPrimGroup;
m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@ -2064,6 +2066,34 @@ namespace OpenSim.Region.Environment.Scenes
}
}
protected void HandleLogOffUserFromGrid(ulong regionHandle, LLUUID AvatarID, LLUUID RegionSecret, string message)
{
if (RegionInfo.RegionHandle == regionHandle)
{
ScenePresence loggingOffUser = null;
loggingOffUser = GetScenePresence(AvatarID);
if (loggingOffUser != null)
{
if (RegionSecret == loggingOffUser.ControllingClient.SecureSessionId)
{
loggingOffUser.ControllingClient.Kick(message);
// Give them a second to receive the message!
System.Threading.Thread.Sleep(1000);
loggingOffUser.ControllingClient.Close(true);
}
else
{
m_log.Info("[USERLOGOFF]: System sending the LogOff user message failed to sucessfully authenticate");
}
}
else
{
m_log.InfoFormat("[USERLOGOFF]: Got a logoff request for {0} but the user isn't here. The user might already have been logged out", AvatarID.ToString());
}
}
}
/// <summary>
/// Add a caps handler for the given agent. If the CAPS handler already exists for this agent,
/// then it is replaced by a new CAPS handler.

View File

@ -58,6 +58,7 @@ namespace OpenSim.Region.Environment.Scenes
public event RegionUp OnRegionUp;
public event ChildAgentUpdate OnChildAgentUpdate;
public event RemoveKnownRegionsFromAvatarList OnRemoveKnownRegionFromAvatar;
public event LogOffUser OnLogOffUser;
private AgentCrossing handlerAvatarCrossingIntoRegion = null; // OnAvatarCrossingIntoRegion;
private ExpectUserDelegate handlerExpectUser = null; // OnExpectUser;
@ -67,6 +68,7 @@ namespace OpenSim.Region.Environment.Scenes
private RegionUp handlerRegionUp = null; // OnRegionUp;
private ChildAgentUpdate handlerChildAgentUpdate = null; // OnChildAgentUpdate;
private RemoveKnownRegionsFromAvatarList handlerRemoveKnownRegionFromAvatar = null; // OnRemoveKnownRegionFromAvatar;
private LogOffUser handlerLogOffUser = null;
public KillObjectDelegate KillObject;
public string _debugRegionName = String.Empty;
@ -105,6 +107,7 @@ namespace OpenSim.Region.Environment.Scenes
regionCommsHost.OnCloseAgentConnection += CloseConnection;
regionCommsHost.OnRegionUp += newRegionUp;
regionCommsHost.OnChildAgentUpdate += ChildAgentUpdate;
regionCommsHost.OnLogOffUser += GridLogOffUser;
}
else
{
@ -121,6 +124,7 @@ namespace OpenSim.Region.Environment.Scenes
{
if (regionCommsHost != null)
{
regionCommsHost.OnLogOffUser -= GridLogOffUser;
regionCommsHost.OnChildAgentUpdate -= ChildAgentUpdate;
regionCommsHost.OnRegionUp -= newRegionUp;
regionCommsHost.OnExpectUser -= NewUserConnection;
@ -150,6 +154,15 @@ namespace OpenSim.Region.Environment.Scenes
}
}
protected void GridLogOffUser(ulong regionHandle, LLUUID AgentID, LLUUID RegionSecret, string message)
{
handlerLogOffUser = OnLogOffUser;
if (handlerLogOffUser != null)
{
handlerLogOffUser(regionHandle, AgentID, RegionSecret, message);
}
}
protected bool newRegionUp(RegionInfo region)
{
handlerRegionUp = OnRegionUp;

View File

@ -596,6 +596,7 @@ namespace OpenSim.Region.Environment.Scenes
m_scene.SendAllSceneObjectsToClient(this);
m_scene.EventManager.TriggerOnMakeRootAgent(this);
m_scene.CommsManager.UserService.UpdateUserCurrentRegion(UUID, m_scene.RegionInfo.RegionID, m_scene.RegionInfo.RegionHandle);
//m_gotAllObjectsInScene = true;
//}