diff options
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 59 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs | 20 |
2 files changed, 69 insertions, 10 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 82358d8..5713e88 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); |
@@ -590,6 +604,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
590 | return; | 604 | return; |
591 | } | 605 | } |
592 | 606 | ||
607 | Thread.Sleep(30000); | ||
608 | |||
593 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) | 609 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) |
594 | { | 610 | { |
595 | m_log.DebugFormat( | 611 | m_log.DebugFormat( |
@@ -598,6 +614,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
598 | 614 | ||
599 | return; | 615 | return; |
600 | } | 616 | } |
617 | else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
618 | { | ||
619 | m_log.DebugFormat( | ||
620 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.", | ||
621 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
622 | |||
623 | return; | ||
624 | } | ||
601 | 625 | ||
602 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. | 626 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. |
603 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); | 627 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); |
@@ -657,12 +681,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
657 | 681 | ||
658 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); | 682 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); |
659 | 683 | ||
684 | // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to | ||
685 | // establish th econnection to the destination which makes it return true. | ||
686 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
687 | { | ||
688 | m_log.DebugFormat( | ||
689 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent", | ||
690 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
691 | |||
692 | return; | ||
693 | } | ||
694 | |||
660 | // A common teleport failure occurs when we can send CreateAgent to the | 695 | // A common teleport failure occurs when we can send CreateAgent to the |
661 | // destination region but the viewer cannot establish the connection (e.g. due to network issues between | 696 | // destination region but the viewer cannot establish the connection (e.g. due to network issues between |
662 | // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then | 697 | // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then |
663 | // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail(). | 698 | // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail(). |
664 | if (!UpdateAgent(reg, finalDestination, agent, sp)) | 699 | if (!UpdateAgent(reg, finalDestination, agent, sp)) |
665 | { | 700 | { |
701 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
702 | { | ||
703 | m_log.DebugFormat( | ||
704 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.", | ||
705 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
706 | |||
707 | return; | ||
708 | } | ||
709 | |||
666 | m_log.WarnFormat( | 710 | m_log.WarnFormat( |
667 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", | 711 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", |
668 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | 712 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); |
@@ -677,7 +721,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
677 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", | 721 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", |
678 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | 722 | sp.Name, finalDestination.RegionName, sp.Scene.Name); |
679 | 723 | ||
680 | CleanupAbortedInterRegionTeleport(sp, finalDestination); | 724 | CleanupFailedInterRegionTeleport(sp, finalDestination); |
681 | 725 | ||
682 | return; | 726 | return; |
683 | } | 727 | } |
@@ -706,6 +750,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
706 | // that the client contacted the destination before we close things here. | 750 | // that the client contacted the destination before we close things here. |
707 | if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) | 751 | if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) |
708 | { | 752 | { |
753 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
754 | { | ||
755 | m_log.DebugFormat( | ||
756 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.", | ||
757 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
758 | |||
759 | return; | ||
760 | } | ||
761 | |||
709 | m_log.WarnFormat( | 762 | m_log.WarnFormat( |
710 | "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", | 763 | "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", |
711 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | 764 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); |
@@ -772,7 +825,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
772 | /// <remarks> | 825 | /// <remarks> |
773 | /// <param name='sp'> </param> | 826 | /// <param name='sp'> </param> |
774 | /// <param name='finalDestination'></param> | 827 | /// <param name='finalDestination'></param> |
775 | protected virtual void CleanupAbortedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination) | 828 | protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination) |
776 | { | 829 | { |
777 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | 830 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); |
778 | 831 | ||
@@ -794,7 +847,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
794 | /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param> | 847 | /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param> |
795 | protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason) | 848 | protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason) |
796 | { | 849 | { |
797 | CleanupAbortedInterRegionTeleport(sp, finalDestination); | 850 | CleanupFailedInterRegionTeleport(sp, finalDestination); |
798 | 851 | ||
799 | sp.ControllingClient.SendTeleportFailed( | 852 | sp.ControllingClient.SendTeleportFailed( |
800 | string.Format( | 853 | string.Format( |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs index 7314727..fc02916 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 | } |