diff options
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 57 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs | 20 |
2 files changed, 67 insertions, 10 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 195d7a9..25334b9 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -167,6 +167,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
167 | 167 | ||
168 | if (!DisableInterRegionTeleportCancellation) | 168 | if (!DisableInterRegionTeleportCancellation) |
169 | client.OnTeleportCancel += OnClientCancelTeleport; | 169 | client.OnTeleportCancel += OnClientCancelTeleport; |
170 | |||
171 | client.OnConnectionClosed += OnConnectionClosed; | ||
170 | } | 172 | } |
171 | 173 | ||
172 | public virtual void Close() {} | 174 | public virtual void Close() {} |
@@ -185,6 +187,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
185 | 187 | ||
186 | #region Agent Teleports | 188 | #region Agent Teleports |
187 | 189 | ||
190 | private void OnConnectionClosed(IClientAPI client) | ||
191 | { | ||
192 | if (client.IsLoggingOut) | ||
193 | { | ||
194 | m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting); | ||
195 | |||
196 | m_log.DebugFormat( | ||
197 | "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout", | ||
198 | client.Name, Scene.Name); | ||
199 | } | ||
200 | } | ||
201 | |||
188 | private void OnClientCancelTeleport(IClientAPI client) | 202 | private void OnClientCancelTeleport(IClientAPI client) |
189 | { | 203 | { |
190 | m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling); | 204 | m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling); |
@@ -603,6 +617,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
603 | 617 | ||
604 | return; | 618 | return; |
605 | } | 619 | } |
620 | else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
621 | { | ||
622 | m_log.DebugFormat( | ||
623 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.", | ||
624 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
625 | |||
626 | return; | ||
627 | } | ||
606 | 628 | ||
607 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. | 629 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. |
608 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); | 630 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); |
@@ -662,12 +684,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
662 | 684 | ||
663 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); | 685 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); |
664 | 686 | ||
687 | // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to | ||
688 | // establish th econnection to the destination which makes it return true. | ||
689 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
690 | { | ||
691 | m_log.DebugFormat( | ||
692 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent", | ||
693 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
694 | |||
695 | return; | ||
696 | } | ||
697 | |||
665 | // A common teleport failure occurs when we can send CreateAgent to the | 698 | // A common teleport failure occurs when we can send CreateAgent to the |
666 | // destination region but the viewer cannot establish the connection (e.g. due to network issues between | 699 | // destination region but the viewer cannot establish the connection (e.g. due to network issues between |
667 | // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then | 700 | // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then |
668 | // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail(). | 701 | // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail(). |
669 | if (!UpdateAgent(reg, finalDestination, agent, sp)) | 702 | if (!UpdateAgent(reg, finalDestination, agent, sp)) |
670 | { | 703 | { |
704 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
705 | { | ||
706 | m_log.DebugFormat( | ||
707 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.", | ||
708 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
709 | |||
710 | return; | ||
711 | } | ||
712 | |||
671 | m_log.WarnFormat( | 713 | m_log.WarnFormat( |
672 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", | 714 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", |
673 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | 715 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); |
@@ -682,7 +724,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
682 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", | 724 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", |
683 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | 725 | sp.Name, finalDestination.RegionName, sp.Scene.Name); |
684 | 726 | ||
685 | CleanupAbortedInterRegionTeleport(sp, finalDestination); | 727 | CleanupFailedInterRegionTeleport(sp, finalDestination); |
686 | 728 | ||
687 | return; | 729 | return; |
688 | } | 730 | } |
@@ -711,6 +753,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
711 | // that the client contacted the destination before we close things here. | 753 | // that the client contacted the destination before we close things here. |
712 | if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) | 754 | if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) |
713 | { | 755 | { |
756 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
757 | { | ||
758 | m_log.DebugFormat( | ||
759 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.", | ||
760 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
761 | |||
762 | return; | ||
763 | } | ||
764 | |||
714 | m_log.WarnFormat( | 765 | m_log.WarnFormat( |
715 | "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", | 766 | "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", |
716 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | 767 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); |
@@ -777,7 +828,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
777 | /// <remarks> | 828 | /// <remarks> |
778 | /// <param name='sp'> </param> | 829 | /// <param name='sp'> </param> |
779 | /// <param name='finalDestination'></param> | 830 | /// <param name='finalDestination'></param> |
780 | protected virtual void CleanupAbortedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination) | 831 | protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination) |
781 | { | 832 | { |
782 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | 833 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); |
783 | 834 | ||
@@ -799,7 +850,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
799 | /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param> | 850 | /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param> |
800 | protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason) | 851 | protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason) |
801 | { | 852 | { |
802 | CleanupAbortedInterRegionTeleport(sp, finalDestination); | 853 | CleanupFailedInterRegionTeleport(sp, finalDestination); |
803 | 854 | ||
804 | sp.ControllingClient.SendTeleportFailed( | 855 | sp.ControllingClient.SendTeleportFailed( |
805 | string.Format( | 856 | string.Format( |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs index b4f09ac..e903383 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs | |||
@@ -51,11 +51,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
51 | /// This is a state machine. | 51 | /// This is a state machine. |
52 | /// | 52 | /// |
53 | /// [Entry] => Preparing | 53 | /// [Entry] => Preparing |
54 | /// Preparing => { Transferring || Cancelling || CleaningUp || [Exit] } | 54 | /// Preparing => { Transferring || Cancelling || CleaningUp || Aborting || [Exit] } |
55 | /// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp } | 55 | /// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp || Aborting } |
56 | /// Cancelling => CleaningUp | 56 | /// Cancelling => CleaningUp || Aborting |
57 | /// ReceivedAtDestination => CleaningUp | 57 | /// ReceivedAtDestination => CleaningUp || Aborting |
58 | /// CleaningUp => [Exit] | 58 | /// CleaningUp => [Exit] |
59 | /// Aborting => [Exit] | ||
59 | /// | 60 | /// |
60 | /// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp | 61 | /// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp |
61 | /// However, any state can transition to CleaningUp if the teleport has failed. | 62 | /// However, any state can transition to CleaningUp if the teleport has failed. |
@@ -66,7 +67,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
66 | Transferring, // The agent is in the process of being transferred to a destination | 67 | Transferring, // The agent is in the process of being transferred to a destination |
67 | ReceivedAtDestination, // The destination has notified us that the agent has been successfully received | 68 | ReceivedAtDestination, // The destination has notified us that the agent has been successfully received |
68 | CleaningUp, // The agent is being changed to child/removed after a transfer | 69 | CleaningUp, // The agent is being changed to child/removed after a transfer |
69 | Cancelling // The user has cancelled the teleport but we have yet to act upon this. | 70 | Cancelling, // The user has cancelled the teleport but we have yet to act upon this. |
71 | Aborting // The transfer is aborting. Unlike Cancelling, no compensating actions should be performed | ||
70 | } | 72 | } |
71 | 73 | ||
72 | /// <summary> | 74 | /// <summary> |
@@ -134,7 +136,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
134 | // Illegal to try and update an agent that's not actually in transit. | 136 | // Illegal to try and update an agent that's not actually in transit. |
135 | if (!m_agentsInTransit.ContainsKey(id)) | 137 | if (!m_agentsInTransit.ContainsKey(id)) |
136 | { | 138 | { |
137 | if (newState != AgentTransferState.Cancelling) | 139 | if (newState != AgentTransferState.Cancelling && newState != AgentTransferState.Aborting) |
138 | failureMessage = string.Format( | 140 | failureMessage = string.Format( |
139 | "Agent with ID {0} is not registered as in transit in {1}", | 141 | "Agent with ID {0} is not registered as in transit in {1}", |
140 | id, m_mod.Scene.RegionInfo.RegionName); | 142 | id, m_mod.Scene.RegionInfo.RegionName); |
@@ -145,7 +147,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
145 | { | 147 | { |
146 | oldState = m_agentsInTransit[id]; | 148 | oldState = m_agentsInTransit[id]; |
147 | 149 | ||
148 | if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp) | 150 | if (newState == AgentTransferState.Aborting) |
151 | { | ||
152 | transitionOkay = true; | ||
153 | } | ||
154 | else if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp) | ||
149 | { | 155 | { |
150 | transitionOkay = true; | 156 | transitionOkay = true; |
151 | } | 157 | } |