aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorDiva Canto2013-07-22 11:54:35 -0700
committerDiva Canto2013-07-24 14:27:58 -0700
commit3891a8946bb72c9256d8de4185bf4a72c90be859 (patch)
tree3c4e2ca2468c287e1c0ea711ad6808bef0d82449 /OpenSim
parentFurther tweaks on TPs: not sending the callback URL and instead waiting 15sec... (diff)
downloadopensim-SC_OLD-3891a8946bb72c9256d8de4185bf4a72c90be859.zip
opensim-SC_OLD-3891a8946bb72c9256d8de4185bf4a72c90be859.tar.gz
opensim-SC_OLD-3891a8946bb72c9256d8de4185bf4a72c90be859.tar.bz2
opensim-SC_OLD-3891a8946bb72c9256d8de4185bf4a72c90be859.tar.xz
New Teleport protocol (V2), still compatible with V1 and older. (version of the destination is being checked)
In this new protocol, and as committed before, the viewer is not sent EnableSimulator/EstablishChildCommunication for the destination. Instead, it is sent TeleportFinish directly. TeleportFinish, in turn, makes the viewer send a UserCircuitCode packet followed by CompleteMovementIntoRegion packet. These 2 packets tend to occur one after the other almost immediately to the point that when CMIR arrives the client is not even connected yet and that packet is ignored (there might have been some race conditions here before); then the viewer sends CMIR again within 5-8 secs. But the delay between them may be higher in busier regions, which may lead to race conditions. This commit improves the process so there are are no race conditions at the destination. CompleteMovement (triggered by the viewer) waits until Update has been sent from the origin. Update, in turn, waits until there is a *root* scene presence -- so making sure CompleteMovement has run MakeRoot. In other words, there are two threadlets at the destination, one from the viewer and one from the origin region, waiting for each other to do the right thing. That makes it safe to close the agent at the origin upon return of the Update call without having to wait for callback, because we are absolutely sure that the viewer knows it is in th new region. Note also that in the V1 protocol, the destination was getting UseCircuitCode from the viewer twice -- once on EstablishAgentCommunication and then again on TeleportFinish. The second UCC was being ignored, but it shows how we were not following the expected steps...
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/ChildAgentDataUpdate.cs11
-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
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;
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