If an agent is still registered as 'in transit' by the source region, don't allow an immediate teleport back.

This is to help relieve a race condition when an agent teleports then immediately attempts to teleport back before the source region has properly cleaned up/demoted the old ScenePresence.
This is rare in viewers but much more possible via scripting or region module.
However, more needs to be done since virtually all clean up happens after the transit flag is cleared .
Possibly need to add a 'cleaning up' state to in transit.
This change required making the EntityTransferModule and HGEntityTransferModule per-region rather than shared, in order to allow separate transit lists.
Changes were also required in LocalSimulationConnector.
Tested in standalone, grid and with local and remote region crossings with attachments.
This commit is contained in:
Justin Clark-Casey (justincc)
2012-05-24 00:31:14 +01:00
parent bc543c1797
commit 459c7635af
6 changed files with 235 additions and 195 deletions

View File

@@ -46,7 +46,7 @@ using Nini.Config;
namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
public class EntityTransferModule : ISharedRegionModule, IEntityTransferModule
public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -65,9 +65,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
public bool EnableWaitForCallbackFromTeleportDest { get; set; }
protected bool m_Enabled = false;
protected Scene m_aScene;
protected List<Scene> m_Scenes = new List<Scene>();
protected Scene m_scene;
protected List<UUID> m_agentsInTransit;
private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
@@ -129,10 +131,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (!m_Enabled)
return;
if (m_aScene == null)
m_aScene = scene;
m_scene = scene;
m_Scenes.Add(scene);
scene.RegisterModuleInterface<IEntityTransferModule>(this);
scene.EventManager.OnNewClient += OnNewClient;
}
@@ -143,27 +143,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
}
public virtual void Close()
{
if (!m_Enabled)
return;
}
public virtual void Close() {}
public virtual void RemoveRegion(Scene scene)
{
if (!m_Enabled)
return;
if (scene == m_aScene)
m_aScene = null;
public virtual void RemoveRegion(Scene scene) {}
m_Scenes.Remove(scene);
}
public virtual void RegionLoaded(Scene scene)
{
if (!m_Enabled)
return;
}
public virtual void RegionLoaded(Scene scene) {}
#endregion
@@ -294,7 +278,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
uint x = 0, y = 0;
Utils.LongToUInts(regionHandle, out x, out y);
GridRegion reg = m_aScene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
GridRegion reg = m_scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
if (reg != null)
{
@@ -441,7 +425,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
string reason;
string version;
if (!m_aScene.SimulationService.QueryAccess(
if (!m_scene.SimulationService.QueryAccess(
finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
{
sp.ControllingClient.SendTeleportFailed(reason);
@@ -660,7 +644,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
EnableChildAgents(sp);
// Finally, kill the agent we just created at the destination.
m_aScene.SimulationService.CloseAgent(finalDestination, sp.UUID);
m_scene.SimulationService.CloseAgent(finalDestination, sp.UUID);
sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
}
@@ -668,7 +652,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout)
{
logout = false;
bool success = m_aScene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason);
bool success = m_scene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason);
if (success)
sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout);
@@ -678,7 +662,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent)
{
return m_aScene.SimulationService.UpdateAgent(finalDestination, agent);
return m_scene.SimulationService.UpdateAgent(finalDestination, agent);
}
protected virtual void SetCallbackURL(AgentData agent, RegionInfo region)
@@ -730,7 +714,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return false;
}
#endregion
#region Landmark Teleport
@@ -742,7 +725,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// <param name="position"></param>
public virtual void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm)
{
GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
GridRegion info = m_scene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
if (info == null)
{
@@ -763,12 +746,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.Name, client.AgentId);
//OpenSim.Services.Interfaces.PresenceInfo pinfo = m_aScene.PresenceService.GetAgent(client.SessionId);
GridUserInfo uinfo = m_aScene.GridUserService.GetGridUserInfo(client.AgentId.ToString());
//OpenSim.Services.Interfaces.PresenceInfo pinfo = m_scene.PresenceService.GetAgent(client.SessionId);
GridUserInfo uinfo = m_scene.GridUserService.GetGridUserInfo(client.AgentId.ToString());
if (uinfo != null)
{
GridRegion regionInfo = m_aScene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID);
GridRegion regionInfo = m_scene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID);
if (regionInfo == null)
{
// can't find the Home region: Tell viewer and abort
@@ -1625,7 +1608,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
#region Agent Arrived
public void AgentArrivedAtDestination(UUID id)
{
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Agent {0} released", id);
ResetFromTransit(id);
}
@@ -1896,8 +1878,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
//// And the new channel...
//if (m_interregionCommsOut != null)
// successYN = m_interregionCommsOut.SendCreateObject(newRegionHandle, grp, true);
if (m_aScene.SimulationService != null)
successYN = m_aScene.SimulationService.CreateObject(destination, newPosition, grp, true);
if (m_scene.SimulationService != null)
successYN = m_scene.SimulationService.CreateObject(destination, newPosition, grp, true);
if (successYN)
{
@@ -2004,7 +1986,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// </summary>
/// <returns>true if the agent is in the process of being teleported, false otherwise.</returns>
/// <param name='id'>The agent ID</para></param>
protected bool IsInTransit(UUID id)
public bool IsInTransit(UUID id)
{
lock (m_agentsInTransit)
return m_agentsInTransit.Contains(id);
@@ -2024,10 +2006,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (m_agentsInTransit.Contains(id))
{
m_agentsInTransit.Remove(id);
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Agent {0} cleared from transit in {1}",
id, m_scene.RegionInfo.RegionName);
return true;
}
}
m_log.WarnFormat(
"[ENTITY TRANSFER MODULE]: Agent {0} requested to clear from transit in {1} but was already cleared.",
id, m_scene.RegionInfo.RegionName);
return false;
}

View File

@@ -45,11 +45,11 @@ using Nini.Config;
namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
public class HGEntityTransferModule : EntityTransferModule, ISharedRegionModule, IEntityTransferModule, IUserAgentVerificationModule
public class HGEntityTransferModule
: EntityTransferModule, INonSharedRegionModule, IEntityTransferModule, IUserAgentVerificationModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private bool m_Initialized = false;
private int m_levelHGTeleport = 0;
private GatekeeperServiceConnector m_GatekeeperConnector;
@@ -64,6 +64,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
public override void Initialise(IConfigSource source)
{
IConfig moduleConfig = source.Configs["Modules"];
if (moduleConfig != null)
{
string name = moduleConfig.GetString("EntityTransferModule", "");
@@ -82,10 +83,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
public override void AddRegion(Scene scene)
{
base.AddRegion(scene);
if (m_Enabled)
{
scene.RegisterModuleInterface<IUserAgentVerificationModule>(this);
}
}
protected override void OnNewClient(IClientAPI client)
@@ -98,24 +98,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
public override void RegionLoaded(Scene scene)
{
base.RegionLoaded(scene);
if (m_Enabled)
if (!m_Initialized)
{
m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
m_Initialized = true;
}
m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
}
public override void RemoveRegion(Scene scene)
{
base.AddRegion(scene);
if (m_Enabled)
{
scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this);
}
}
if (m_Enabled)
scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this);
}
#endregion
@@ -123,8 +117,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
protected override GridRegion GetFinalDestination(GridRegion region)
{
int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, region.RegionID);
int flags = m_scene.GridService.GetRegionFlags(m_scene.RegionInfo.ScopeID, region.RegionID);
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags);
if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
{
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID);
@@ -135,6 +130,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: GetHyperlinkRegion to Gatekeeper {0} failed", region.ServerURI);
return real_destination;
}
return region;
}
@@ -143,7 +139,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (base.NeedsClosing(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
return true;
int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, reg.RegionID);
int flags = m_scene.GridService.GetRegionFlags(m_scene.RegionInfo.ScopeID, reg.RegionID);
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
return true;
@@ -156,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (logout)
{
// Log them out of this grid
m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
m_scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
}
}
@@ -165,7 +161,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: CreateAgent {0} {1}", reg.ServerURI, finalDestination.ServerURI);
reason = string.Empty;
logout = false;
int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, reg.RegionID);
int flags = m_scene.GridService.GetRegionFlags(m_scene.RegionInfo.ScopeID, reg.RegionID);
if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
{
// this user is going to another grid
@@ -205,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
"[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.Name, client.AgentId);
// Let's find out if this is a foreign user or a local user
IUserManagement uMan = m_aScene.RequestModuleInterface<IUserManagement>();
IUserManagement uMan = m_scene.RequestModuleInterface<IUserManagement>();
if (uMan != null && uMan.IsLocalGridUser(id))
{
// local grid user
@@ -262,19 +258,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
{
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}",
(lm.Gatekeeper == string.Empty) ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position);
if (lm.Gatekeeper == string.Empty)
{
base.RequestTeleportLandmark(remoteClient, lm);
return;
}
GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
GridRegion info = m_scene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
// Local region?
if (info != null)
{
((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position,
Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
return;
}
else
@@ -285,6 +283,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
GridRegion gatekeeper = new GridRegion();
gatekeeper.ServerURI = lm.Gatekeeper;
GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(lm.RegionID));
if (finalDestination != null)
{
ScenePresence sp = scene.GetScenePresence(remoteClient.AgentId);
@@ -314,8 +313,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
IUserAgentService security = new UserAgentServiceConnector(url);
return security.VerifyClient(aCircuit.SessionID, token);
}
else
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent {0} {1} does not have a HomeURI OH NO!", aCircuit.firstname, aCircuit.lastname);
else
{
m_log.DebugFormat(
"[HG ENTITY TRANSFER MODULE]: Agent {0} {1} does not have a HomeURI OH NO!",
aCircuit.firstname, aCircuit.lastname);
}
return false;
}
@@ -332,8 +335,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
// Let's find out if this is a foreign user or a local user
IUserManagement uMan = m_aScene.RequestModuleInterface<IUserManagement>();
UserAccount account = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, obj.AgentId);
IUserManagement uMan = m_scene.RequestModuleInterface<IUserManagement>();
UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, obj.AgentId);
if (uMan != null && uMan.IsLocalGridUser(obj.AgentId))
{
// local grid user
@@ -356,7 +359,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
#endregion
private GridRegion MakeRegion(AgentCircuitData aCircuit)
{
GridRegion region = new GridRegion();
@@ -373,6 +375,5 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), (int)0);
return region;
}
}
}
}