From d8ebf2fc9d7d2e50735d50e75f7153f487efe958 Mon Sep 17 00:00:00 2001 From: diva Date: Thu, 1 Jan 2009 19:42:24 +0000 Subject: Major changes in interregion communications. This breaks compatibility with older versions, and may result is all sorts of weirdnesses when interacting with sims in older versions. Changes: - Introducing synchronous Teleports. Now the receiving region calls back the sending region after the client has been made a root agent there, that is, after client sends CompleteMovement to the destination. - SendCloseAgent moved from OGS1 Remoting to RESTComms. --- .../Hypergrid/HGSceneCommunicationService.cs | 34 +++++-- OpenSim/Region/Environment/Scenes/Scene.cs | 21 +++- .../Scenes/SceneCommunicationService.cs | 106 ++++++++++++++------- OpenSim/Region/Environment/Scenes/ScenePresence.cs | 16 +++- 4 files changed, 130 insertions(+), 47 deletions(-) (limited to 'OpenSim/Region/Environment/Scenes') diff --git a/OpenSim/Region/Environment/Scenes/Hypergrid/HGSceneCommunicationService.cs b/OpenSim/Region/Environment/Scenes/Hypergrid/HGSceneCommunicationService.cs index bcd378f..abf4065 100644 --- a/OpenSim/Region/Environment/Scenes/Hypergrid/HGSceneCommunicationService.cs +++ b/OpenSim/Region/Environment/Scenes/Hypergrid/HGSceneCommunicationService.cs @@ -256,15 +256,16 @@ namespace OpenSim.Region.Environment.Scenes.Hypergrid // return; //} + SetInTransit(avatar.UUID); // Let's send a full update of the agent. This is a synchronous call. AgentData agent = new AgentData(); avatar.CopyTo(agent); agent.Position = new Vector3(-1, -1, -1); // this means ignore position info; UGH!!!! + agent.CallbackURI = "http://" + m_regionInfo.ExternalHostName + ":" + m_regionInfo.HttpPort + + "/agent/" + avatar.UUID.ToString() + "/" + avatar.Scene.RegionInfo.RegionHandle.ToString() + "/release/"; m_interregionCommsOut.SendChildAgentUpdate(reg.RegionHandle, agent); - avatar.MakeChildAgent(); - m_log.DebugFormat( "[CAPS]: Sending new CAPS seed url {0} to client {1}", agentCircuit.CapsPath, avatar.UUID); @@ -288,17 +289,32 @@ namespace OpenSim.Region.Environment.Scenes.Hypergrid /// Hypergrid mod stop /// + + // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which + // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation + // that the client contacted the destination before we send the attachments and close things here. + if (!WaitForCallback(avatar.UUID)) + { + // Client never contacted destination. Let's restore everything back + avatar.ControllingClient.SendTeleportFailed("Problems connecting to destination."); + + ResetFromTransit(avatar.UUID); + // Yikes! We should just have a ref to scene here. + avatar.Scene.InformClientOfNeighbours(avatar); + + // Finally, kill the agent we just created at the destination. + m_interregionCommsOut.SendCloseAgent(reg.RegionHandle, avatar.UUID); + + return; + } + + // Can't go back from here if (KiPrimitive != null) { KiPrimitive(avatar.LocalId); } - // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which - // trigers a whole shebang of things there, including MakeRoot. So let's wait plenty before - // we send the attachments and close things here. - // It would be nice if the client would tell us when that whole thing is done, so we wouldn't have - // to use this Thread.Sleep voodoo - Thread.Sleep(4000); + avatar.MakeChildAgent(); // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it avatar.CrossAttachmentsIntoNewRegion(reg.RegionHandle, true); @@ -310,7 +326,7 @@ namespace OpenSim.Region.Environment.Scenes.Hypergrid /// if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY) || isHyperLink) { - Thread.Sleep(8000); + Thread.Sleep(5000); avatar.Close(); CloseConnection(avatar.UUID); } diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 56b5df6..13b9169 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -2692,7 +2692,7 @@ namespace OpenSim.Region.Environment.Scenes { m_sceneGridService.OnExpectUser += NewUserConnection; m_sceneGridService.OnAvatarCrossingIntoRegion += AgentCrossing; - m_sceneGridService.OnCloseAgentConnection += CloseConnection; + m_sceneGridService.OnCloseAgentConnection += IncomingCloseAgent; m_sceneGridService.OnRegionUp += OtherRegionUp; //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; m_sceneGridService.OnExpectPrim += IncomingInterRegionPrimGroup; @@ -2724,7 +2724,7 @@ namespace OpenSim.Region.Environment.Scenes m_sceneGridService.OnRegionUp -= OtherRegionUp; m_sceneGridService.OnExpectUser -= NewUserConnection; m_sceneGridService.OnAvatarCrossingIntoRegion -= AgentCrossing; - m_sceneGridService.OnCloseAgentConnection -= CloseConnection; + m_sceneGridService.OnCloseAgentConnection -= IncomingCloseAgent; m_sceneGridService.OnGetLandData -= GetLandData; if (m_interregionCommsIn != null) @@ -2979,12 +2979,22 @@ namespace OpenSim.Region.Environment.Scenes return false; } + public virtual bool IncomingReleaseAgent(UUID id) + { + return m_sceneGridService.ReleaseAgent(id); + } + + public void SendReleaseAgent(ulong regionHandle, UUID id, string uri) + { + m_interregionCommsOut.SendReleaseAgent(regionHandle, id, uri); + } + /// /// Tell a single agent to disconnect from the region. /// /// /// - public bool CloseConnection(UUID agentID) + public bool IncomingCloseAgent(UUID agentID) { ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); if (presence != null) @@ -3013,9 +3023,10 @@ namespace OpenSim.Region.Environment.Scenes presence.ControllingClient.SendShutdownConnectionNotice(); } presence.ControllingClient.Close(true); - + return true; } - return true; + // Agent not here + return false; } /// diff --git a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs index 2bf81d8..da3a9d3 100644 --- a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs @@ -55,6 +55,8 @@ namespace OpenSim.Region.Environment.Scenes protected RegionCommsListener regionCommsHost; + protected List m_agentsInTransit; + public event AgentCrossing OnAvatarCrossingIntoRegion; public event ExpectUserDelegate OnExpectUser; public event ExpectPrimDelegate OnExpectPrim; @@ -82,6 +84,7 @@ namespace OpenSim.Region.Environment.Scenes public SceneCommunicationService(CommunicationsManager commsMan) { m_commsProvider = commsMan; + m_agentsInTransit = new List(); } /// @@ -546,8 +549,7 @@ namespace OpenSim.Region.Environment.Scenes /// private void SendChildAgentDataUpdateAsync(AgentData cAgentData, ulong regionHandle) { - m_log.Info("[INTERGRID]: Informing neighbors about my agent in " + m_regionInfo.RegionName); - //bool regionAccepted = m_commsProvider.InterRegion.ChildAgentUpdate(regionHandle, cAgentData); + //m_log.Info("[INTERGRID]: Informing neighbors about my agent in " + m_regionInfo.RegionName); try { //m_commsProvider.InterRegion.ChildAgentUpdate(regionHandle, cAgentData); @@ -608,29 +610,10 @@ namespace OpenSim.Region.Environment.Scenes { m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle); - //bool regionAccepted = m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); // let's do our best, but there's not much we can do if the neighbour doesn't accept. - m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); - - //if (regionAccepted) - //{ - // m_log.Info("[INTERGRID]: Completed sending agent Close agent Request to neighbor"); - - //} - //else - //{ - // m_log.Info("[INTERGRID]: Failed sending agent Close agent Request to neighbor"); - //} - - //// We remove the list of known regions from the agent's known region list through an event - //// to scene, because, if an agent logged of, it's likely that there will be no scene presence - //// by the time we get to this part of the method. - //handlerRemoveKnownRegionFromAvatar = OnRemoveKnownRegionFromAvatar; - //if (handlerRemoveKnownRegionFromAvatar != null) - //{ - // handlerRemoveKnownRegionFromAvatar(agentID, regionlst); - //} + //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); + m_interregionCommsOut.SendCloseAgent(regionHandle, agentID); } private void SendCloseChildAgentCompleted(IAsyncResult iar) @@ -860,15 +843,16 @@ namespace OpenSim.Region.Environment.Scenes // return; //} + SetInTransit(avatar.UUID); // Let's send a full update of the agent. This is a synchronous call. AgentData agent = new AgentData(); avatar.CopyTo(agent); agent.Position = new Vector3(-1, -1, -1); // this means ignore position info; UGH!!!! + agent.CallbackURI = "http://" + m_regionInfo.ExternalHostName + ":" + m_regionInfo.HttpPort + + "/agent/" + avatar.UUID.ToString() + "/" + avatar.Scene.RegionInfo.RegionHandle.ToString() + "/release/"; m_interregionCommsOut.SendChildAgentUpdate(reg.RegionHandle, agent); - avatar.MakeChildAgent(); - m_log.DebugFormat( "[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, avatar.UUID); @@ -885,17 +869,32 @@ namespace OpenSim.Region.Environment.Scenes teleportFlags, capsPath); } + + // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which + // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation + // that the client contacted the destination before we send the attachments and close things here. + if (!WaitForCallback(avatar.UUID)) + { + // Client never contacted destination. Let's restore everything back + avatar.ControllingClient.SendTeleportFailed("Problems connecting to destination."); + + ResetFromTransit(avatar.UUID); + // Yikes! We should just have a ref to scene here. + avatar.Scene.InformClientOfNeighbours(avatar); + + // Finally, kill the agent we just created at the destination. + m_interregionCommsOut.SendCloseAgent(reg.RegionHandle, avatar.UUID); + + return; + } + + // Can't go back from here if (KiPrimitive != null) { KiPrimitive(avatar.LocalId); } - // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which - // trigers a whole shebang of things there, including MakeRoot. So let's wait plenty before - // we send the attachments and close things here. - // We need to change this part of the protocol. The receiving region should tell this region - // when it's ok to continue. - Thread.Sleep(4000); + avatar.MakeChildAgent(); // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it avatar.CrossAttachmentsIntoNewRegion(reg.RegionHandle, true); @@ -904,7 +903,7 @@ namespace OpenSim.Region.Environment.Scenes if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY)) { - Thread.Sleep(8000); + Thread.Sleep(5000); avatar.Close(); CloseConnection(avatar.UUID); } @@ -947,6 +946,49 @@ namespace OpenSim.Region.Environment.Scenes } } + protected bool WaitForCallback(UUID id) + { + int count = 20; + while (m_agentsInTransit.Contains(id) && count-- > 0) + { + //Console.WriteLine(" >>> Waiting... " + count); + Thread.Sleep(1000); + } + + if (count > 0) + return true; + else + return false; + } + + public bool ReleaseAgent(UUID id) + { + //Console.WriteLine(" >>> ReleaseAgent called <<< "); + return ResetFromTransit(id); + } + + protected void SetInTransit(UUID id) + { + lock (m_agentsInTransit) + { + if (!m_agentsInTransit.Contains(id)) + m_agentsInTransit.Add(id); + } + } + + protected bool ResetFromTransit(UUID id) + { + lock (m_agentsInTransit) + { + if (m_agentsInTransit.Contains(id)) + { + m_agentsInTransit.Remove(id); + return true; + } + } + return false; + } + private List NeighbourHandles(List neighbours) { List handles = new List(); diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs index 23dc9be..166e051 100644 --- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs @@ -217,6 +217,10 @@ namespace OpenSim.Region.Environment.Scenes private Dictionary m_updateTimes = new Dictionary(); + // For teleports and crossings callbacks + string m_callbackURI; + ulong m_rootRegionHandle; + #region Properties /// @@ -1000,6 +1004,7 @@ namespace OpenSim.Region.Environment.Scenes /// public void CompleteMovement() { + //Console.WriteLine("\n CompleteMovement \n"); Vector3 look = Velocity; if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) { @@ -1013,6 +1018,12 @@ namespace OpenSim.Region.Environment.Scenes m_isChildAgent = false; MakeRootAgent(AbsolutePosition, false); + + if ((m_callbackURI != null) && !m_callbackURI.Equals("")) + { + Scene.SendReleaseAgent(m_rootRegionHandle, UUID, m_callbackURI); + m_callbackURI = null; + } } } @@ -2582,7 +2593,7 @@ namespace OpenSim.Region.Environment.Scenes if (!IsChildAgent) return; - //Console.WriteLine(" >>> ChildAgentDataUpdate <<<"); + //Console.WriteLine(" >>> ChildAgentDataUpdate <<< " + rRegionX + "-" + rRegionY); int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; @@ -2615,6 +2626,9 @@ namespace OpenSim.Region.Environment.Scenes if (m_scene.m_seeIntoRegionFromNeighbor) m_pendingObjects = null; + m_callbackURI = cAgentData.CallbackURI; + m_rootRegionHandle = Util.UIntsToLong(rRegionX * Constants.RegionSize, rRegionY * Constants.RegionSize); + //cAgentData.AVHeight; //cAgentData.regionHandle; //m_velocity = cAgentData.Velocity; -- cgit v1.1