aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs314
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs36
2 files changed, 235 insertions, 115 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index b97a0f6..a3bd388 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -151,7 +151,7 @@ namespace OpenSim.Region.Framework.Scenes
151 public SynchronizeSceneHandler SynchronizeScene; 151 public SynchronizeSceneHandler SynchronizeScene;
152 152
153 /// <summary> 153 /// <summary>
154 /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. 154 /// Used to prevent simultaneous calls to code that adds and removes agents.
155 /// </summary> 155 /// </summary>
156 private object m_removeClientLock = new object(); 156 private object m_removeClientLock = new object();
157 157
@@ -1312,7 +1312,7 @@ namespace OpenSim.Region.Framework.Scenes
1312 Thread.Sleep(500); 1312 Thread.Sleep(500);
1313 1313
1314 // Stop all client threads. 1314 // Stop all client threads.
1315 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1315 ForEachScenePresence(delegate(ScenePresence avatar) { IncomingCloseAgent(avatar.UUID, false); });
1316 1316
1317 m_log.Debug("[SCENE]: Persisting changed objects"); 1317 m_log.Debug("[SCENE]: Persisting changed objects");
1318 EventManager.TriggerSceneShuttingDown(this); 1318 EventManager.TriggerSceneShuttingDown(this);
@@ -2972,7 +2972,7 @@ namespace OpenSim.Region.Framework.Scenes
2972 { 2972 {
2973 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 2973 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2974 2974
2975 sp.ControllingClient.Close(); 2975 IncomingCloseAgent(sp.UUID, false);
2976 } 2976 }
2977 else 2977 else
2978 { 2978 {
@@ -3384,47 +3384,48 @@ namespace OpenSim.Region.Framework.Scenes
3384 3384
3385 public override void RemoveClient(UUID agentID, bool closeChildAgents) 3385 public override void RemoveClient(UUID agentID, bool closeChildAgents)
3386 { 3386 {
3387// CheckHeartbeat(); 3387 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3388 bool isChildAgent = false;
3389 AgentCircuitData acd;
3390 3388
3391 lock (m_removeClientLock) 3389 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3390 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3391 // However, will keep for now just in case.
3392 if (acd == null)
3392 { 3393 {
3393 acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3394 m_log.ErrorFormat(
3395 "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name);
3394 3396
3395 if (acd == null) 3397 return;
3396 { 3398 }
3397 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); 3399 else
3398 return; 3400 {
3399 } 3401 m_authenticateHandler.RemoveCircuit(agentID);
3400 else
3401 {
3402 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3403 // simultaneously.
3404 // We also need to remove by agent ID since NPCs will have no circuit code.
3405 m_authenticateHandler.RemoveCircuit(agentID);
3406 }
3407 } 3402 }
3408 3403
3404 // TODO: Can we now remove this lock?
3409 lock (acd) 3405 lock (acd)
3410 { 3406 {
3407 bool isChildAgent = false;
3408
3411 ScenePresence avatar = GetScenePresence(agentID); 3409 ScenePresence avatar = GetScenePresence(agentID);
3412 3410
3411 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3412 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3413 // However, will keep for now just in case.
3413 if (avatar == null) 3414 if (avatar == null)
3414 { 3415 {
3415 m_log.WarnFormat( 3416 m_log.ErrorFormat(
3416 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); 3417 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3417 3418
3418 return; 3419 return;
3419 } 3420 }
3420 3421
3421 try 3422 try
3422 { 3423 {
3423 isChildAgent = avatar.IsChildAgent; 3424 isChildAgent = avatar.IsChildAgent;
3424 3425
3425 m_log.DebugFormat( 3426 m_log.DebugFormat(
3426 "[SCENE]: Removing {0} agent {1} {2} from {3}", 3427 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3427 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); 3428 isChildAgent ? "child" : "root", avatar.Name, agentID, Name);
3428 3429
3429 // Don't do this to root agents, it's not nice for the viewer 3430 // Don't do this to root agents, it's not nice for the viewer
3430 if (closeChildAgents && isChildAgent) 3431 if (closeChildAgents && isChildAgent)
@@ -3587,13 +3588,13 @@ namespace OpenSim.Region.Framework.Scenes
3587 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of 3588 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3588 /// the LLUDP stack). 3589 /// the LLUDP stack).
3589 /// </remarks> 3590 /// </remarks>
3590 /// <param name="agent">CircuitData of the agent who is connecting</param> 3591 /// <param name="acd">CircuitData of the agent who is connecting</param>
3591 /// <param name="reason">Outputs the reason for the false response on this string</param> 3592 /// <param name="reason">Outputs the reason for the false response on this string</param>
3592 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3593 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
3593 /// or other applications where a full grid/Hypergrid presence may not be required.</param> 3594 /// or other applications where a full grid/Hypergrid presence may not be required.</param>
3594 /// <returns>True if the region accepts this agent. False if it does not. False will 3595 /// <returns>True if the region accepts this agent. False if it does not. False will
3595 /// also return a reason.</returns> 3596 /// also return a reason.</returns>
3596 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) 3597 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, out string reason, bool requirePresenceLookup)
3597 { 3598 {
3598 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3599 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3599 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3600 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
@@ -3613,15 +3614,15 @@ namespace OpenSim.Region.Framework.Scenes
3613 m_log.DebugFormat( 3614 m_log.DebugFormat(
3614 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", 3615 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})",
3615 RegionInfo.RegionName, 3616 RegionInfo.RegionName,
3616 (agent.child ? "child" : "root"), 3617 (acd.child ? "child" : "root"),
3617 agent.firstname, 3618 acd.firstname,
3618 agent.lastname, 3619 acd.lastname,
3619 agent.AgentID, 3620 acd.AgentID,
3620 agent.circuitcode, 3621 acd.circuitcode,
3621 agent.IPAddress, 3622 acd.IPAddress,
3622 agent.Viewer, 3623 acd.Viewer,
3623 ((TPFlags)teleportFlags).ToString(), 3624 ((TPFlags)teleportFlags).ToString(),
3624 agent.startpos 3625 acd.startpos
3625 ); 3626 );
3626 3627
3627 if (!LoginsEnabled) 3628 if (!LoginsEnabled)
@@ -3639,7 +3640,7 @@ namespace OpenSim.Region.Framework.Scenes
3639 { 3640 {
3640 foreach (string viewer in m_AllowedViewers) 3641 foreach (string viewer in m_AllowedViewers)
3641 { 3642 {
3642 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3643 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3643 { 3644 {
3644 ViewerDenied = false; 3645 ViewerDenied = false;
3645 break; 3646 break;
@@ -3656,7 +3657,7 @@ namespace OpenSim.Region.Framework.Scenes
3656 { 3657 {
3657 foreach (string viewer in m_BannedViewers) 3658 foreach (string viewer in m_BannedViewers)
3658 { 3659 {
3659 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3660 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3660 { 3661 {
3661 ViewerDenied = true; 3662 ViewerDenied = true;
3662 break; 3663 break;
@@ -3668,61 +3669,112 @@ namespace OpenSim.Region.Framework.Scenes
3668 { 3669 {
3669 m_log.DebugFormat( 3670 m_log.DebugFormat(
3670 "[SCENE]: Access denied for {0} {1} using {2}", 3671 "[SCENE]: Access denied for {0} {1} using {2}",
3671 agent.firstname, agent.lastname, agent.Viewer); 3672 acd.firstname, acd.lastname, acd.Viewer);
3672 reason = "Access denied, your viewer is banned by the region owner"; 3673 reason = "Access denied, your viewer is banned by the region owner";
3673 return false; 3674 return false;
3674 } 3675 }
3675 3676
3676 ILandObject land; 3677 ILandObject land;
3678 ScenePresence sp;
3677 3679
3678 lock (agent) 3680 lock (m_removeClientLock)
3679 { 3681 {
3680 ScenePresence sp = GetScenePresence(agent.AgentID); 3682 sp = GetScenePresence(acd.AgentID);
3681 3683
3682 if (sp != null) 3684 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3685 // closed.
3686 if (sp != null && sp.IsChildAgent && sp.LifecycleState == ScenePresenceState.Running)
3683 { 3687 {
3684 if (!sp.IsChildAgent) 3688 m_log.DebugFormat(
3685 { 3689 "[SCENE]: Reusing existing child scene presence for {0} in {1}", sp.Name, Name);
3686 // We have a root agent. Is it in transit?
3687 if (!EntityTransferModule.IsInTransit(sp.UUID))
3688 {
3689 // We have a zombie from a crashed session.
3690 // Or the same user is trying to be root twice here, won't work.
3691 // Kill it.
3692 m_log.WarnFormat(
3693 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3694 sp.Name, sp.UUID, RegionInfo.RegionName);
3695 3690
3696 if (sp.ControllingClient != null) 3691 // In the case where, for example, an A B C D region layout, an avatar may
3697 sp.ControllingClient.Close(true); 3692 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
3693 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3694 if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3695 {
3696 m_log.DebugFormat(
3697 "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3698 sp.Name, Name);
3698 3699
3699 sp = null; 3700 sp.DoNotCloseAfterTeleport = true;
3700 }
3701 //else
3702 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
3703 } 3701 }
3704 else 3702 else if (EntityTransferModule.IsInTransit(sp.UUID))
3705 { 3703 {
3706 // We have a child agent here 3704 m_log.DebugFormat(
3705 "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt previous end-of-teleport close.",
3706 sp.Name, Name);
3707
3707 sp.DoNotCloseAfterTeleport = true; 3708 sp.DoNotCloseAfterTeleport = true;
3708 //m_log.WarnFormat("[SCENE]: Existing child scene presence for {0} {1} in {2}", sp.Name, sp.UUID, RegionInfo.RegionName);
3709 } 3709 }
3710 } 3710 }
3711 }
3712
3713 // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will
3714 // allow unpredictable things to happen.
3715 if (sp != null)
3716 {
3717 const int polls = 10;
3718 const int pollInterval = 1000;
3719 int pollsLeft = polls;
3720
3721 while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0)
3722 Thread.Sleep(pollInterval);
3723
3724 if (sp.LifecycleState == ScenePresenceState.Removing)
3725 {
3726 m_log.WarnFormat(
3727 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3728 sp.Name, Name, polls * pollInterval / 1000);
3729
3730 return false;
3731 }
3732 else if (polls != pollsLeft)
3733 {
3734 m_log.DebugFormat(
3735 "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.",
3736 sp.Name, Name, polls * pollInterval / 1000);
3737 }
3738 }
3739
3740 // TODO: can we remove this lock?
3741 lock (acd)
3742 {
3743 if (sp != null && !sp.IsChildAgent)
3744 {
3745 // We have a root agent. Is it in transit?
3746 if (!EntityTransferModule.IsInTransit(sp.UUID))
3747 {
3748 // We have a zombie from a crashed session.
3749 // Or the same user is trying to be root twice here, won't work.
3750 // Kill it.
3751 m_log.WarnFormat(
3752 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3753 sp.Name, sp.UUID, RegionInfo.RegionName);
3754
3755 if (sp.ControllingClient != null)
3756 IncomingCloseAgent(sp.UUID, true);
3757
3758 sp = null;
3759 }
3760 //else
3761 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
3762 }
3711 3763
3712 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags. 3764 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags.
3713 // We need the circuit data here for some of the subsequent checks. (groups, for example) 3765 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3714 // If the checks fail, we remove the circuit. 3766 // If the checks fail, we remove the circuit.
3715 agent.teleportFlags = teleportFlags; 3767 acd.teleportFlags = teleportFlags;
3716 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 3768 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3717 3769
3718 land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); 3770 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
3719 3771
3720 // On login test land permisions 3772 // On login test land permisions
3721 if (vialogin) 3773 if (vialogin)
3722 { 3774 {
3723 if (land != null && !TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) 3775 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3724 { 3776 {
3725 m_authenticateHandler.RemoveCircuit(agent.circuitcode); 3777 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3726 return false; 3778 return false;
3727 } 3779 }
3728 } 3780 }
@@ -3733,9 +3785,9 @@ namespace OpenSim.Region.Framework.Scenes
3733 { 3785 {
3734 try 3786 try
3735 { 3787 {
3736 if (!VerifyUserPresence(agent, out reason)) 3788 if (!VerifyUserPresence(acd, out reason))
3737 { 3789 {
3738 m_authenticateHandler.RemoveCircuit(agent.circuitcode); 3790 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3739 return false; 3791 return false;
3740 } 3792 }
3741 } 3793 }
@@ -3744,16 +3796,16 @@ namespace OpenSim.Region.Framework.Scenes
3744 m_log.ErrorFormat( 3796 m_log.ErrorFormat(
3745 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3797 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3746 3798
3747 m_authenticateHandler.RemoveCircuit(agent.circuitcode); 3799 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3748 return false; 3800 return false;
3749 } 3801 }
3750 } 3802 }
3751 3803
3752 try 3804 try
3753 { 3805 {
3754 if (!AuthorizeUser(agent, SeeIntoRegion, out reason)) 3806 if (!AuthorizeUser(acd, SeeIntoRegion, out reason))
3755 { 3807 {
3756 m_authenticateHandler.RemoveCircuit(agent.circuitcode); 3808 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3757 return false; 3809 return false;
3758 } 3810 }
3759 } 3811 }
@@ -3762,19 +3814,19 @@ namespace OpenSim.Region.Framework.Scenes
3762 m_log.ErrorFormat( 3814 m_log.ErrorFormat(
3763 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 3815 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
3764 3816
3765 m_authenticateHandler.RemoveCircuit(agent.circuitcode); 3817 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3766 return false; 3818 return false;
3767 } 3819 }
3768 3820
3769 m_log.InfoFormat( 3821 m_log.InfoFormat(
3770 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 3822 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3771 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, 3823 Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname,
3772 agent.AgentID, agent.circuitcode); 3824 acd.AgentID, acd.circuitcode);
3773 3825
3774 if (CapsModule != null) 3826 if (CapsModule != null)
3775 { 3827 {
3776 CapsModule.SetAgentCapsSeeds(agent); 3828 CapsModule.SetAgentCapsSeeds(acd);
3777 CapsModule.CreateCaps(agent.AgentID); 3829 CapsModule.CreateCaps(acd.AgentID);
3778 } 3830 }
3779 } 3831 }
3780 else 3832 else
@@ -3787,14 +3839,14 @@ namespace OpenSim.Region.Framework.Scenes
3787 { 3839 {
3788 m_log.DebugFormat( 3840 m_log.DebugFormat(
3789 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 3841 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3790 agent.AgentID, RegionInfo.RegionName); 3842 acd.AgentID, RegionInfo.RegionName);
3791 3843
3792 sp.AdjustKnownSeeds(); 3844 sp.AdjustKnownSeeds();
3793 3845
3794 if (CapsModule != null) 3846 if (CapsModule != null)
3795 { 3847 {
3796 CapsModule.SetAgentCapsSeeds(agent); 3848 CapsModule.SetAgentCapsSeeds(acd);
3797 CapsModule.CreateCaps(agent.AgentID); 3849 CapsModule.CreateCaps(acd.AgentID);
3798 } 3850 }
3799 } 3851 }
3800 } 3852 }
@@ -3802,23 +3854,23 @@ namespace OpenSim.Region.Framework.Scenes
3802 // Try caching an incoming user name much earlier on to see if this helps with an issue 3854 // Try caching an incoming user name much earlier on to see if this helps with an issue
3803 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName 3855 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName
3804 // request for the HG avatar appears to trigger before the user name is cached. 3856 // request for the HG avatar appears to trigger before the user name is cached.
3805 CacheUserName(null, agent); 3857 CacheUserName(null, acd);
3806 } 3858 }
3807 3859
3808 if (vialogin) 3860 if (vialogin)
3809 { 3861 {
3810// CleanDroppedAttachments(); 3862// CleanDroppedAttachments();
3811 3863
3812 if (TestBorderCross(agent.startpos, Cardinals.E)) 3864 if (TestBorderCross(acd.startpos, Cardinals.E))
3813 { 3865 {
3814 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); 3866 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3815 agent.startpos.X = crossedBorder.BorderLine.Z - 1; 3867 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3816 } 3868 }
3817 3869
3818 if (TestBorderCross(agent.startpos, Cardinals.N)) 3870 if (TestBorderCross(acd.startpos, Cardinals.N))
3819 { 3871 {
3820 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); 3872 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
3821 agent.startpos.Y = crossedBorder.BorderLine.Z - 1; 3873 acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
3822 } 3874 }
3823 3875
3824 //Mitigate http://opensimulator.org/mantis/view.php?id=3522 3876 //Mitigate http://opensimulator.org/mantis/view.php?id=3522
@@ -3828,39 +3880,39 @@ namespace OpenSim.Region.Framework.Scenes
3828 { 3880 {
3829 lock (EastBorders) 3881 lock (EastBorders)
3830 { 3882 {
3831 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 3883 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
3832 { 3884 {
3833 m_log.Warn("FIX AGENT POSITION"); 3885 m_log.Warn("FIX AGENT POSITION");
3834 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 3886 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3835 if (agent.startpos.Z > 720) 3887 if (acd.startpos.Z > 720)
3836 agent.startpos.Z = 720; 3888 acd.startpos.Z = 720;
3837 } 3889 }
3838 } 3890 }
3839 lock (NorthBorders) 3891 lock (NorthBorders)
3840 { 3892 {
3841 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 3893 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
3842 { 3894 {
3843 m_log.Warn("FIX Agent POSITION"); 3895 m_log.Warn("FIX Agent POSITION");
3844 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 3896 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
3845 if (agent.startpos.Z > 720) 3897 if (acd.startpos.Z > 720)
3846 agent.startpos.Z = 720; 3898 acd.startpos.Z = 720;
3847 } 3899 }
3848 } 3900 }
3849 } else 3901 } else
3850 { 3902 {
3851 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 3903 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
3852 { 3904 {
3853 m_log.Warn("FIX AGENT POSITION"); 3905 m_log.Warn("FIX AGENT POSITION");
3854 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 3906 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3855 if (agent.startpos.Z > 720) 3907 if (acd.startpos.Z > 720)
3856 agent.startpos.Z = 720; 3908 acd.startpos.Z = 720;
3857 } 3909 }
3858 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 3910 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
3859 { 3911 {
3860 m_log.Warn("FIX Agent POSITION"); 3912 m_log.Warn("FIX Agent POSITION");
3861 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 3913 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
3862 if (agent.startpos.Z > 720) 3914 if (acd.startpos.Z > 720)
3863 agent.startpos.Z = 720; 3915 acd.startpos.Z = 720;
3864 } 3916 }
3865 } 3917 }
3866 3918
@@ -3876,12 +3928,12 @@ namespace OpenSim.Region.Framework.Scenes
3876 { 3928 {
3877 // We have multiple SpawnPoints, Route the agent to a random or sequential one 3929 // We have multiple SpawnPoints, Route the agent to a random or sequential one
3878 if (SpawnPointRouting == "random") 3930 if (SpawnPointRouting == "random")
3879 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( 3931 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
3880 telehub.AbsolutePosition, 3932 telehub.AbsolutePosition,
3881 telehub.GroupRotation 3933 telehub.GroupRotation
3882 ); 3934 );
3883 else 3935 else
3884 agent.startpos = spawnpoints[SpawnPoint()].GetLocation( 3936 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
3885 telehub.AbsolutePosition, 3937 telehub.AbsolutePosition,
3886 telehub.GroupRotation 3938 telehub.GroupRotation
3887 ); 3939 );
@@ -3889,7 +3941,7 @@ namespace OpenSim.Region.Framework.Scenes
3889 else 3941 else
3890 { 3942 {
3891 // We have a single SpawnPoint and will route the agent to it 3943 // We have a single SpawnPoint and will route the agent to it
3892 agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 3944 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
3893 } 3945 }
3894 3946
3895 return true; 3947 return true;
@@ -3900,7 +3952,7 @@ namespace OpenSim.Region.Framework.Scenes
3900 { 3952 {
3901 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3953 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
3902 { 3954 {
3903 agent.startpos = land.LandData.UserLocation; 3955 acd.startpos = land.LandData.UserLocation;
3904 } 3956 }
3905 } 3957 }
3906 } 3958 }
@@ -4360,11 +4412,51 @@ namespace OpenSim.Region.Framework.Scenes
4360 /// </param> 4412 /// </param>
4361 public bool IncomingCloseAgent(UUID agentID, bool force) 4413 public bool IncomingCloseAgent(UUID agentID, bool force)
4362 { 4414 {
4363 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4415 ScenePresence sp;
4364 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4416
4365 if (presence != null) 4417 lock (m_removeClientLock)
4418 {
4419 sp = GetScenePresence(agentID);
4420
4421 if (sp == null)
4422 {
4423 m_log.DebugFormat(
4424 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in {1}",
4425 agentID, Name);
4426
4427 return false;
4428 }
4429
4430 if (sp.LifecycleState != ScenePresenceState.Running)
4431 {
4432 m_log.DebugFormat(
4433 "[SCENE]: Called RemoveClient() for {0} in {1} but presence is already in state {2}",
4434 sp.Name, Name, sp.LifecycleState);
4435
4436 return false;
4437 }
4438
4439 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4440 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4441 // want to obey this close since C may have renewed the child agent lease on B.
4442 if (sp.DoNotCloseAfterTeleport)
4443 {
4444 m_log.DebugFormat(
4445 "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4446 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4447
4448 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4449 sp.DoNotCloseAfterTeleport = false;
4450
4451 return false;
4452 }
4453
4454 sp.LifecycleState = ScenePresenceState.Removing;
4455 }
4456
4457 if (sp != null)
4366 { 4458 {
4367 presence.ControllingClient.Close(force); 4459 sp.ControllingClient.Close(force);
4368 return true; 4460 return true;
4369 } 4461 }
4370 4462
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1b8c276..aac80f7 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -74,6 +74,8 @@ namespace OpenSim.Region.Framework.Scenes
74 74
75 public class ScenePresence : EntityBase, IScenePresence 75 public class ScenePresence : EntityBase, IScenePresence
76 { 76 {
77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
78
77// ~ScenePresence() 79// ~ScenePresence()
78// { 80// {
79// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); 81// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
@@ -85,10 +87,27 @@ namespace OpenSim.Region.Framework.Scenes
85 m_scene.EventManager.TriggerScenePresenceUpdated(this); 87 m_scene.EventManager.TriggerScenePresenceUpdated(this);
86 } 88 }
87 89
88 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
89
90 public PresenceType PresenceType { get; private set; } 90 public PresenceType PresenceType { get; private set; }
91 91
92 private ScenePresenceStateMachine m_stateMachine;
93
94 /// <summary>
95 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine
96 /// for more details.
97 /// </summary>
98 public ScenePresenceState LifecycleState
99 {
100 get
101 {
102 return m_stateMachine.GetState();
103 }
104
105 set
106 {
107 m_stateMachine.SetState(value);
108 }
109 }
110
92// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 111// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
93 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 112 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
94 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); 113 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
@@ -766,7 +785,7 @@ namespace OpenSim.Region.Framework.Scenes
766 785
767 public ScenePresence( 786 public ScenePresence(
768 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 787 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
769 { 788 {
770 AttachmentsSyncLock = new Object(); 789 AttachmentsSyncLock = new Object();
771 AllowMovement = true; 790 AllowMovement = true;
772 IsChildAgent = true; 791 IsChildAgent = true;
@@ -811,6 +830,8 @@ namespace OpenSim.Region.Framework.Scenes
811 SetDirectionVectors(); 830 SetDirectionVectors();
812 831
813 Appearance = appearance; 832 Appearance = appearance;
833
834 m_stateMachine = new ScenePresenceStateMachine(this);
814 } 835 }
815 836
816 public void RegisterToEvents() 837 public void RegisterToEvents()
@@ -879,7 +900,7 @@ namespace OpenSim.Region.Framework.Scenes
879 /// </summary> 900 /// </summary>
880 public void MakeRootAgent(Vector3 pos, bool isFlying) 901 public void MakeRootAgent(Vector3 pos, bool isFlying)
881 { 902 {
882 m_log.DebugFormat( 903 m_log.InfoFormat(
883 "[SCENE]: Upgrading child to root agent for {0} in {1}", 904 "[SCENE]: Upgrading child to root agent for {0} in {1}",
884 Name, m_scene.RegionInfo.RegionName); 905 Name, m_scene.RegionInfo.RegionName);
885 906
@@ -887,6 +908,11 @@ namespace OpenSim.Region.Framework.Scenes
887 908
888 IsChildAgent = false; 909 IsChildAgent = false;
889 910
911 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
912 // set and prevent the close of the connection on a subsequent re-teleport.
913 // Should not be needed if we are not trying to tell this region to close
914// DoNotCloseAfterTeleport = false;
915
890 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 916 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
891 if (gm != null) 917 if (gm != null)
892 Grouptitle = gm.GetGroupTitle(m_uuid); 918 Grouptitle = gm.GetGroupTitle(m_uuid);
@@ -3738,6 +3764,8 @@ namespace OpenSim.Region.Framework.Scenes
3738 // m_reprioritizationTimer.Dispose(); 3764 // m_reprioritizationTimer.Dispose();
3739 3765
3740 RemoveFromPhysicalScene(); 3766 RemoveFromPhysicalScene();
3767
3768 LifecycleState = ScenePresenceState.Removed;
3741 } 3769 }
3742 3770
3743 public void AddAttachment(SceneObjectGroup gobj) 3771 public void AddAttachment(SceneObjectGroup gobj)