aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs68
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs263
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs18
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs33
5 files changed, 310 insertions, 74 deletions
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;
29using System.Xml; 29using System.Xml;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using System.Timers; 33using System.Timers;
34using Timer = System.Timers.Timer;
33using OpenMetaverse; 35using OpenMetaverse;
34using log4net; 36using log4net;
35using Nini.Config; 37using 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