diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 314 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/ScenePresence.cs | 36 |
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) |