diff options
Diffstat (limited to '')
6 files changed, 316 insertions, 79 deletions
diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index 9fc048b..1c5f558 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs | |||
@@ -287,7 +287,7 @@ namespace OpenSim.Framework | |||
287 | public Vector3 AtAxis; | 287 | public Vector3 AtAxis; |
288 | public Vector3 LeftAxis; | 288 | public Vector3 LeftAxis; |
289 | public Vector3 UpAxis; | 289 | public Vector3 UpAxis; |
290 | public bool ChangedGrid; | 290 | public bool SenderWantsToWaitForRoot; |
291 | 291 | ||
292 | public float Far; | 292 | public float Far; |
293 | public float Aspect; | 293 | public float Aspect; |
@@ -356,8 +356,9 @@ namespace OpenSim.Framework | |||
356 | args["left_axis"] = OSD.FromString(LeftAxis.ToString()); | 356 | args["left_axis"] = OSD.FromString(LeftAxis.ToString()); |
357 | args["up_axis"] = OSD.FromString(UpAxis.ToString()); | 357 | args["up_axis"] = OSD.FromString(UpAxis.ToString()); |
358 | 358 | ||
359 | 359 | //backwards compatibility | |
360 | args["changed_grid"] = OSD.FromBoolean(ChangedGrid); | 360 | args["changed_grid"] = OSD.FromBoolean(SenderWantsToWaitForRoot); |
361 | args["wait_for_root"] = OSD.FromBoolean(SenderWantsToWaitForRoot); | ||
361 | args["far"] = OSD.FromReal(Far); | 362 | args["far"] = OSD.FromReal(Far); |
362 | args["aspect"] = OSD.FromReal(Aspect); | 363 | args["aspect"] = OSD.FromReal(Aspect); |
363 | 364 | ||
@@ -526,8 +527,8 @@ namespace OpenSim.Framework | |||
526 | if (args["up_axis"] != null) | 527 | if (args["up_axis"] != null) |
527 | Vector3.TryParse(args["up_axis"].AsString(), out AtAxis); | 528 | Vector3.TryParse(args["up_axis"].AsString(), out AtAxis); |
528 | 529 | ||
529 | if (args["changed_grid"] != null) | 530 | if (args.ContainsKey("wait_for_root") && args["wait_for_root"] != null) |
530 | ChangedGrid = args["changed_grid"].AsBoolean(); | 531 | SenderWantsToWaitForRoot = args["wait_for_root"].AsBoolean(); |
531 | 532 | ||
532 | if (args["far"] != null) | 533 | if (args["far"] != null) |
533 | Far = (float)(args["far"].AsReal()); | 534 | Far = (float)(args["far"].AsReal()); |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 37fd252..1b72b26 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -1257,6 +1257,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1257 | // UseCircuitCode handling | 1257 | // UseCircuitCode handling |
1258 | if (packet.Type == PacketType.UseCircuitCode) | 1258 | if (packet.Type == PacketType.UseCircuitCode) |
1259 | { | 1259 | { |
1260 | m_log.DebugFormat("[ZZZ]: In the dungeon: UseCircuitCode"); | ||
1260 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | 1261 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the |
1261 | // buffer. | 1262 | // buffer. |
1262 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | 1263 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; |
@@ -1265,6 +1266,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1265 | 1266 | ||
1266 | return; | 1267 | return; |
1267 | } | 1268 | } |
1269 | else if (packet.Type == PacketType.CompleteAgentMovement) | ||
1270 | { | ||
1271 | // Send ack straight away to let the viewer know that we got it. | ||
1272 | SendAckImmediate(endPoint, packet.Header.Sequence); | ||
1273 | |||
1274 | m_log.DebugFormat("[ZZZ]: In the dungeon: CompleteAgentMovement"); | ||
1275 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | ||
1276 | // buffer. | ||
1277 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
1278 | |||
1279 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); | ||
1280 | |||
1281 | return; | ||
1282 | } | ||
1268 | 1283 | ||
1269 | // Determine which agent this packet came from | 1284 | // Determine which agent this packet came from |
1270 | IClientAPI client; | 1285 | IClientAPI client; |
@@ -1604,6 +1619,56 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1604 | } | 1619 | } |
1605 | } | 1620 | } |
1606 | 1621 | ||
1622 | private void HandleCompleteMovementIntoRegion(object o) | ||
1623 | { | ||
1624 | IPEndPoint endPoint = null; | ||
1625 | IClientAPI client = null; | ||
1626 | |||
1627 | try | ||
1628 | { | ||
1629 | object[] array = (object[])o; | ||
1630 | endPoint = (IPEndPoint)array[0]; | ||
1631 | CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1]; | ||
1632 | |||
1633 | // Determine which agent this packet came from | ||
1634 | int count = 10; | ||
1635 | while (!m_scene.TryGetClient(endPoint, out client) && count-- > 0) | ||
1636 | { | ||
1637 | m_log.Debug("[LLUDPSERVER]: Received a CompleteMovementIntoRegion in " + m_scene.RegionInfo.RegionName + " (not ready yet)"); | ||
1638 | Thread.Sleep(200); | ||
1639 | } | ||
1640 | |||
1641 | if (client == null) | ||
1642 | return; | ||
1643 | |||
1644 | IncomingPacket incomingPacket1; | ||
1645 | |||
1646 | // Inbox insertion | ||
1647 | if (UsePools) | ||
1648 | { | ||
1649 | incomingPacket1 = m_incomingPacketPool.GetObject(); | ||
1650 | incomingPacket1.Client = (LLClientView)client; | ||
1651 | incomingPacket1.Packet = packet; | ||
1652 | } | ||
1653 | else | ||
1654 | { | ||
1655 | incomingPacket1 = new IncomingPacket((LLClientView)client, packet); | ||
1656 | } | ||
1657 | |||
1658 | packetInbox.Enqueue(incomingPacket1); | ||
1659 | } | ||
1660 | catch (Exception e) | ||
1661 | { | ||
1662 | m_log.ErrorFormat( | ||
1663 | "[LLUDPSERVER]: CompleteMovementIntoRegion handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", | ||
1664 | endPoint != null ? endPoint.ToString() : "n/a", | ||
1665 | client != null ? client.Name : "unknown", | ||
1666 | client != null ? client.AgentId.ToString() : "unknown", | ||
1667 | e.Message, | ||
1668 | e.StackTrace); | ||
1669 | } | ||
1670 | } | ||
1671 | |||
1607 | /// <summary> | 1672 | /// <summary> |
1608 | /// Send an ack immediately to the given endpoint. | 1673 | /// Send an ack immediately to the given endpoint. |
1609 | /// </summary> | 1674 | /// </summary> |
@@ -1999,6 +2064,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1999 | Packet packet = incomingPacket.Packet; | 2064 | Packet packet = incomingPacket.Packet; |
2000 | LLClientView client = incomingPacket.Client; | 2065 | LLClientView client = incomingPacket.Client; |
2001 | 2066 | ||
2067 | if (packet is CompleteAgentMovementPacket) | ||
2068 | m_log.DebugFormat("[ZZZ]: Received CompleteAgentMovementPacket"); | ||
2069 | |||
2002 | if (client.IsActive) | 2070 | if (client.IsActive) |
2003 | { | 2071 | { |
2004 | m_currentIncomingClient = client; | 2072 | m_currentIncomingClient = client; |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 5124aed..b0c0b1d 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -684,7 +684,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
684 | agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); | 684 | agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); |
685 | } | 685 | } |
686 | 686 | ||
687 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Contacting destination..."); | 687 | if (version.Equals("SIMULATION/0.2")) |
688 | TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason); | ||
689 | else | ||
690 | TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason); | ||
691 | |||
692 | } | ||
693 | |||
694 | private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination, | ||
695 | IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason) | ||
696 | { | ||
697 | ulong destinationHandle = finalDestination.RegionHandle; | ||
698 | AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); | ||
688 | 699 | ||
689 | // Let's create an agent there if one doesn't exist yet. | 700 | // Let's create an agent there if one doesn't exist yet. |
690 | // NOTE: logout will always be false for a non-HG teleport. | 701 | // NOTE: logout will always be false for a non-HG teleport. |
@@ -707,7 +718,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
707 | m_interRegionTeleportCancels.Value++; | 718 | m_interRegionTeleportCancels.Value++; |
708 | 719 | ||
709 | m_log.DebugFormat( | 720 | m_log.DebugFormat( |
710 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", | 721 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", |
711 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | 722 | sp.Name, finalDestination.RegionName, sp.Scene.Name); |
712 | 723 | ||
713 | return; | 724 | return; |
@@ -725,14 +736,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
725 | 736 | ||
726 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. | 737 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. |
727 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); | 738 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); |
728 | 739 | ||
729 | #region old protocol | 740 | IClientIPEndpoint ipepClient; |
730 | 741 | string capsPath = String.Empty; | |
731 | IClientIPEndpoint ipepClient; | ||
732 | if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) | 742 | if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) |
733 | { | 743 | { |
734 | m_log.DebugFormat( | 744 | m_log.DebugFormat( |
735 | "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}", | 745 | "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}", |
736 | finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name); | 746 | finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name); |
737 | 747 | ||
738 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); | 748 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); |
@@ -745,30 +755,30 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
745 | #endregion | 755 | #endregion |
746 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); | 756 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); |
747 | 757 | ||
748 | //if (m_eqModule != null) | 758 | if (m_eqModule != null) |
749 | //{ | 759 | { |
750 | // // The EnableSimulator message makes the client establish a connection with the destination | 760 | // The EnableSimulator message makes the client establish a connection with the destination |
751 | // // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the | 761 | // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the |
752 | // // correct circuit code. | 762 | // correct circuit code. |
753 | // m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID); | 763 | m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID); |
754 | 764 | ||
755 | // // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination | 765 | // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination |
756 | // // simulator to confirm that it has established communication with the viewer. | 766 | // simulator to confirm that it has established communication with the viewer. |
757 | // Thread.Sleep(200); | 767 | Thread.Sleep(200); |
758 | 768 | ||
759 | // // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears | 769 | // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears |
760 | // // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly | 770 | // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly |
761 | // // only on TeleportFinish). This is untested for region teleport between different simulators | 771 | // only on TeleportFinish). This is untested for region teleport between different simulators |
762 | // // though this probably also works. | 772 | // though this probably also works. |
763 | // m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); | 773 | m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); |
764 | //} | 774 | } |
765 | //else | 775 | else |
766 | //{ | 776 | { |
767 | // // XXX: This is a little misleading since we're information the client of its avatar destination, | 777 | // XXX: This is a little misleading since we're information the client of its avatar destination, |
768 | // // which may or may not be a neighbour region of the source region. This path is probably little | 778 | // which may or may not be a neighbour region of the source region. This path is probably little |
769 | // // used anyway (with EQ being the one used). But it is currently being used for test code. | 779 | // used anyway (with EQ being the one used). But it is currently being used for test code. |
770 | // sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); | 780 | sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); |
771 | //} | 781 | } |
772 | } | 782 | } |
773 | else | 783 | else |
774 | { | 784 | { |
@@ -776,15 +786,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
776 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); | 786 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); |
777 | } | 787 | } |
778 | 788 | ||
779 | #endregion old protocol | ||
780 | |||
781 | // Let's send a full update of the agent. This is a synchronous call. | 789 | // Let's send a full update of the agent. This is a synchronous call. |
782 | AgentData agent = new AgentData(); | 790 | AgentData agent = new AgentData(); |
783 | sp.CopyTo(agent); | 791 | sp.CopyTo(agent); |
784 | agent.Position = position; | 792 | agent.Position = agentCircuit.startpos; |
785 | //SetCallbackURL(agent, sp.Scene.RegionInfo); | 793 | SetCallbackURL(agent, sp.Scene.RegionInfo); |
786 | 794 | ||
787 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); | ||
788 | 795 | ||
789 | // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to | 796 | // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to |
790 | // establish th econnection to the destination which makes it return true. | 797 | // establish th econnection to the destination which makes it return true. |
@@ -814,7 +821,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
814 | sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4, | 821 | sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4, |
815 | teleportFlags, capsPath); | 822 | teleportFlags, capsPath); |
816 | } | 823 | } |
817 | 824 | ||
818 | // A common teleport failure occurs when we can send CreateAgent to the | 825 | // A common teleport failure occurs when we can send CreateAgent to the |
819 | // destination region but the viewer cannot establish the connection (e.g. due to network issues between | 826 | // destination region but the viewer cannot establish the connection (e.g. due to network issues between |
820 | // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then | 827 | // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then |
@@ -835,7 +842,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
835 | m_log.WarnFormat( | 842 | m_log.WarnFormat( |
836 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", | 843 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", |
837 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | 844 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); |
838 | 845 | ||
839 | Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); | 846 | Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); |
840 | return; | 847 | return; |
841 | } | 848 | } |
@@ -845,7 +852,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
845 | m_interRegionTeleportCancels.Value++; | 852 | m_interRegionTeleportCancels.Value++; |
846 | 853 | ||
847 | m_log.DebugFormat( | 854 | m_log.DebugFormat( |
848 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", | 855 | "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", |
849 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | 856 | sp.Name, finalDestination.RegionName, sp.Scene.Name); |
850 | 857 | ||
851 | CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.SessionID.ToString(), finalDestination); | 858 | CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.SessionID.ToString(), finalDestination); |
@@ -857,30 +864,30 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
857 | "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", | 864 | "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", |
858 | capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); | 865 | capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); |
859 | 866 | ||
860 | //// TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which | 867 | // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which |
861 | //// trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation | 868 | // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation |
862 | //// that the client contacted the destination before we close things here. | 869 | // that the client contacted the destination before we close things here. |
863 | //if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) | 870 | if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID)) |
864 | //{ | 871 | { |
865 | // if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | 872 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) |
866 | // { | 873 | { |
867 | // m_interRegionTeleportAborts.Value++; | 874 | m_interRegionTeleportAborts.Value++; |
868 | |||
869 | // m_log.DebugFormat( | ||
870 | // "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.", | ||
871 | // sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
872 | |||
873 | // return; | ||
874 | // } | ||
875 | |||
876 | // m_log.WarnFormat( | ||
877 | // "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", | ||
878 | // sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | ||
879 | |||
880 | // Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion."); | ||
881 | 875 | ||
882 | // return; | 876 | m_log.DebugFormat( |
883 | //} | 877 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.", |
878 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
879 | |||
880 | return; | ||
881 | } | ||
882 | |||
883 | m_log.WarnFormat( | ||
884 | "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", | ||
885 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | ||
886 | |||
887 | Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion."); | ||
888 | |||
889 | return; | ||
890 | } | ||
884 | 891 | ||
885 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | 892 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); |
886 | 893 | ||
@@ -914,7 +921,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
914 | // | 921 | // |
915 | // This sleep can be increased if necessary. However, whilst it's active, | 922 | // This sleep can be increased if necessary. However, whilst it's active, |
916 | // an agent cannot teleport back to this region if it has teleported away. | 923 | // an agent cannot teleport back to this region if it has teleported away. |
917 | Thread.Sleep(15000); | 924 | Thread.Sleep(2000); |
918 | 925 | ||
919 | sp.Scene.IncomingCloseAgent(sp.UUID, false); | 926 | sp.Scene.IncomingCloseAgent(sp.UUID, false); |
920 | } | 927 | } |
@@ -925,6 +932,126 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
925 | } | 932 | } |
926 | } | 933 | } |
927 | 934 | ||
935 | private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination, | ||
936 | IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason) | ||
937 | { | ||
938 | ulong destinationHandle = finalDestination.RegionHandle; | ||
939 | AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); | ||
940 | |||
941 | // Let's create an agent there if one doesn't exist yet. | ||
942 | // NOTE: logout will always be false for a non-HG teleport. | ||
943 | bool logout = false; | ||
944 | if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) | ||
945 | { | ||
946 | m_interRegionTeleportFailures.Value++; | ||
947 | |||
948 | sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason)); | ||
949 | |||
950 | m_log.DebugFormat( | ||
951 | "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}", | ||
952 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); | ||
953 | |||
954 | return; | ||
955 | } | ||
956 | |||
957 | // Past this point we have to attempt clean up if the teleport fails, so update transfer state. | ||
958 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); | ||
959 | |||
960 | IClientIPEndpoint ipepClient; | ||
961 | string capsPath = String.Empty; | ||
962 | if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) | ||
963 | { | ||
964 | m_log.DebugFormat( | ||
965 | "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}", | ||
966 | finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name); | ||
967 | |||
968 | //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); | ||
969 | #region IP Translation for NAT | ||
970 | // Uses ipepClient above | ||
971 | if (sp.ClientView.TryGet(out ipepClient)) | ||
972 | { | ||
973 | endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); | ||
974 | } | ||
975 | #endregion | ||
976 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); | ||
977 | } | ||
978 | else | ||
979 | { | ||
980 | agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); | ||
981 | capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); | ||
982 | } | ||
983 | |||
984 | // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator, | ||
985 | // where that neighbour simulator could otherwise request a child agent create on the source which then | ||
986 | // closes our existing agent which is still signalled as root. | ||
987 | //sp.IsChildAgent = true; | ||
988 | |||
989 | // New protocol: send TP Finish directly, without prior ES or EAC. That's what happens in the Linden grid | ||
990 | if (m_eqModule != null) | ||
991 | m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID); | ||
992 | else | ||
993 | sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4, | ||
994 | teleportFlags, capsPath); | ||
995 | |||
996 | m_log.DebugFormat( | ||
997 | "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}", | ||
998 | capsPath, sp.Scene.RegionInfo.RegionName, sp.Name); | ||
999 | |||
1000 | // Let's send a full update of the agent. | ||
1001 | AgentData agent = new AgentData(); | ||
1002 | sp.CopyTo(agent); | ||
1003 | agent.Position = agentCircuit.startpos; | ||
1004 | agent.SenderWantsToWaitForRoot = true; | ||
1005 | //SetCallbackURL(agent, sp.Scene.RegionInfo); | ||
1006 | |||
1007 | // Send the Update. If this returns true, we know the client has contacted the destination | ||
1008 | // via CompleteMovementIntoRegion, so we can let go. | ||
1009 | // If it returns false, something went wrong, and we need to abort. | ||
1010 | m_log.DebugFormat("[ZZZ]: Sending Update"); | ||
1011 | if (!UpdateAgent(reg, finalDestination, agent, sp)) | ||
1012 | { | ||
1013 | if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) | ||
1014 | { | ||
1015 | m_interRegionTeleportAborts.Value++; | ||
1016 | |||
1017 | m_log.DebugFormat( | ||
1018 | "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.", | ||
1019 | sp.Name, finalDestination.RegionName, sp.Scene.Name); | ||
1020 | |||
1021 | return; | ||
1022 | } | ||
1023 | |||
1024 | m_log.WarnFormat( | ||
1025 | "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", | ||
1026 | sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); | ||
1027 | |||
1028 | Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); | ||
1029 | return; | ||
1030 | } | ||
1031 | |||
1032 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | ||
1033 | |||
1034 | // May need to logout or other cleanup | ||
1035 | AgentHasMovedAway(sp, logout); | ||
1036 | |||
1037 | // Well, this is it. The agent is over there. | ||
1038 | KillEntity(sp.Scene, sp.LocalId); | ||
1039 | |||
1040 | // Now let's make it officially a child agent | ||
1041 | sp.MakeChildAgent(); | ||
1042 | |||
1043 | // OK, it got this agent. Let's close some child agents | ||
1044 | sp.CloseChildAgents(newRegionX, newRegionY); | ||
1045 | |||
1046 | // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone | ||
1047 | |||
1048 | if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) | ||
1049 | sp.Scene.IncomingCloseAgent(sp.UUID, false); | ||
1050 | else | ||
1051 | // now we have a child agent in this region. | ||
1052 | sp.Reset(); | ||
1053 | } | ||
1054 | |||
928 | /// <summary> | 1055 | /// <summary> |
929 | /// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation. | 1056 | /// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation. |
930 | /// </summary> | 1057 | /// </summary> |
@@ -938,11 +1065,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
938 | { | 1065 | { |
939 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); | 1066 | m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); |
940 | 1067 | ||
941 | sp.IsChildAgent = false; | 1068 | if (sp.IsChildAgent) // We had set it to child before attempted TP (V1) |
942 | ReInstantiateScripts(sp); | 1069 | { |
943 | 1070 | sp.IsChildAgent = false; | |
944 | EnableChildAgents(sp); | 1071 | ReInstantiateScripts(sp); |
945 | 1072 | ||
1073 | EnableChildAgents(sp); | ||
1074 | } | ||
946 | // Finally, kill the agent we just created at the destination. | 1075 | // Finally, kill the agent we just created at the destination. |
947 | // XXX: Possibly this should be done asynchronously. | 1076 | // XXX: Possibly this should be done asynchronously. |
948 | Scene.SimulationService.CloseAgent(finalDestination, sp.UUID, auth_token); | 1077 | Scene.SimulationService.CloseAgent(finalDestination, sp.UUID, auth_token); |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 6d5039b..7dd10f7 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs | |||
@@ -48,7 +48,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation | |||
48 | /// <summary> | 48 | /// <summary> |
49 | /// Version of this service | 49 | /// Version of this service |
50 | /// </summary> | 50 | /// </summary> |
51 | private const string m_Version = "SIMULATION/0.1"; | 51 | private const string m_Version = "SIMULATION/0.2"; |
52 | 52 | ||
53 | /// <summary> | 53 | /// <summary> |
54 | /// Map region ID to scene. | 54 | /// Map region ID to scene. |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d4ef3d9..da8a1b8 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -4221,6 +4221,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
4221 | } | 4221 | } |
4222 | 4222 | ||
4223 | childAgentUpdate.ChildAgentDataUpdate(cAgentData); | 4223 | childAgentUpdate.ChildAgentDataUpdate(cAgentData); |
4224 | |||
4225 | int ntimes = 20; | ||
4226 | if (cAgentData.SenderWantsToWaitForRoot) | ||
4227 | { | ||
4228 | while (childAgentUpdate.IsChildAgent && ntimes-- > 0) | ||
4229 | Thread.Sleep(500); | ||
4230 | |||
4231 | m_log.DebugFormat( | ||
4232 | "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits", | ||
4233 | childAgentUpdate.Name, childAgentUpdate.UUID, childAgentUpdate.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 20 - ntimes); | ||
4234 | |||
4235 | if (childAgentUpdate.IsChildAgent) | ||
4236 | return false; | ||
4237 | } | ||
4224 | return true; | 4238 | return true; |
4225 | } | 4239 | } |
4226 | return false; | 4240 | return false; |
@@ -4278,10 +4292,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
4278 | m_log.WarnFormat( | 4292 | m_log.WarnFormat( |
4279 | "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", | 4293 | "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", |
4280 | agentID, RegionInfo.RegionName); | 4294 | agentID, RegionInfo.RegionName); |
4281 | // else | ||
4282 | // m_log.DebugFormat( | ||
4283 | // "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits", | ||
4284 | // sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes); | ||
4285 | 4295 | ||
4286 | return sp; | 4296 | return sp; |
4287 | } | 4297 | } |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 6433878..891e04e 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -29,7 +29,9 @@ using System; | |||
29 | using System.Xml; | 29 | using System.Xml; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Threading; | ||
32 | using System.Timers; | 33 | using System.Timers; |
34 | using Timer = System.Timers.Timer; | ||
33 | using OpenMetaverse; | 35 | using OpenMetaverse; |
34 | using log4net; | 36 | using log4net; |
35 | using Nini.Config; | 37 | using Nini.Config; |
@@ -1311,6 +1313,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
1311 | PhysicsActor.Size = new Vector3(0.45f, 0.6f, height); | 1313 | PhysicsActor.Size = new Vector3(0.45f, 0.6f, height); |
1312 | } | 1314 | } |
1313 | 1315 | ||
1316 | private bool WaitForUpdateAgent(IClientAPI client) | ||
1317 | { | ||
1318 | // Before UpdateAgent, m_originRegionID is UUID.Zero; after, it's non-Zero | ||
1319 | int count = 20; | ||
1320 | while (m_originRegionID.Equals(UUID.Zero) && count-- > 0) | ||
1321 | { | ||
1322 | m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.RegionInfo.RegionName); | ||
1323 | Thread.Sleep(200); | ||
1324 | } | ||
1325 | |||
1326 | if (m_originRegionID.Equals(UUID.Zero)) | ||
1327 | { | ||
1328 | // Movement into region will fail | ||
1329 | m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived", client.Name); | ||
1330 | return false; | ||
1331 | } | ||
1332 | |||
1333 | return true; | ||
1334 | } | ||
1335 | |||
1314 | /// <summary> | 1336 | /// <summary> |
1315 | /// Complete Avatar's movement into the region. | 1337 | /// Complete Avatar's movement into the region. |
1316 | /// </summary> | 1338 | /// </summary> |
@@ -1328,6 +1350,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1328 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", | 1350 | "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", |
1329 | client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); | 1351 | client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); |
1330 | 1352 | ||
1353 | if (m_teleportFlags != TeleportFlags.ViaLogin) | ||
1354 | // Let's wait until UpdateAgent (called by departing region) is done | ||
1355 | if (!WaitForUpdateAgent(client)) | ||
1356 | // The sending region never sent the UpdateAgent data, we have to refuse | ||
1357 | return; | ||
1358 | |||
1331 | Vector3 look = Velocity; | 1359 | Vector3 look = Velocity; |
1332 | 1360 | ||
1333 | if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) | 1361 | if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) |
@@ -1348,10 +1376,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1348 | 1376 | ||
1349 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); | 1377 | bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); |
1350 | MakeRootAgent(AbsolutePosition, flying); | 1378 | MakeRootAgent(AbsolutePosition, flying); |
1379 | |||
1380 | // Tell the client that we're totally ready | ||
1351 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); | 1381 | ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); |
1382 | |||
1352 | // Remember in HandleUseCircuitCode, we delayed this to here | 1383 | // Remember in HandleUseCircuitCode, we delayed this to here |
1353 | // This will also send the initial data to clients when TP to a neighboring region. | ||
1354 | // Not ideal, but until we know we're TP-ing from a neighboring region, there's not much we can do | ||
1355 | if (m_teleportFlags > 0) | 1384 | if (m_teleportFlags > 0) |
1356 | SendInitialDataToMe(); | 1385 | SendInitialDataToMe(); |
1357 | 1386 | ||