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. --- OpenSim/Framework/ChildAgentDataUpdate.cs | 7 + OpenSim/Region/Application/OpenSim.cs | 2 +- .../Environment/Interfaces/IInterregionComms.cs | 2 + .../Communications/Local/LocalInterregionComms.cs | 52 +++++-- .../Communications/REST/RESTInterregionComms.cs | 173 ++++++++++++++++++--- .../Hypergrid/HGSceneCommunicationService.cs | 34 ++-- OpenSim/Region/Environment/Scenes/Scene.cs | 21 ++- .../Scenes/SceneCommunicationService.cs | 106 +++++++++---- OpenSim/Region/Environment/Scenes/ScenePresence.cs | 16 +- 9 files changed, 338 insertions(+), 75 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index 257f435..f3ac943 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -144,6 +144,7 @@ namespace OpenSim.Framework byte[] VisualParams; + public string CallbackURI; public OSDMap PackUpdateMessage() { @@ -191,6 +192,9 @@ namespace OpenSim.Framework // Last few fields are still missing + if ((CallbackURI != null) && (!CallbackURI.Equals(""))) + args["callback_uri"] = OSD.FromString(CallbackURI); + return args; } @@ -284,6 +288,9 @@ namespace OpenSim.Framework if (args["active_group_id"] != null) ActiveGroupID = args["active_group_id"].AsUUID(); + + if (args["callback_uri"] != null) + CallbackURI = args["callback_uri"].AsString(); } public AgentData() diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index c3b3a01..b3ca651 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -177,7 +177,7 @@ namespace OpenSim presence.UUID, regionInfo.RegionName)); - presence.Scene.CloseConnection(presence.UUID); + presence.Scene.IncomingCloseAgent(presence.UUID); } } m_console.Notice(""); diff --git a/OpenSim/Region/Environment/Interfaces/IInterregionComms.cs b/OpenSim/Region/Environment/Interfaces/IInterregionComms.cs index b70e885..e197622 100644 --- a/OpenSim/Region/Environment/Interfaces/IInterregionComms.cs +++ b/OpenSim/Region/Environment/Interfaces/IInterregionComms.cs @@ -36,6 +36,8 @@ namespace OpenSim.Region.Environment.Interfaces public interface IInterregionCommsOut { bool SendChildAgentUpdate(ulong regionHandle, AgentData data); + bool SendReleaseAgent(ulong regionHandle, UUID id, string uri); + bool SendCloseAgent(ulong regionHandle, UUID id); } // This may not be needed, but having it here for now. diff --git a/OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs b/OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs index 781bf1c..9f547a2 100644 --- a/OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs +++ b/OpenSim/Region/Environment/Modules/Communications/Local/LocalInterregionComms.cs @@ -120,23 +120,57 @@ namespace OpenSim.Region.Environment.Modules.Communications.Local public bool SendChildAgentUpdate(ulong regionHandle, AgentData cAgentData) { - lock (m_sceneList) + foreach (Scene s in m_sceneList) { - foreach (Scene s in m_sceneList) + if (s.RegionInfo.RegionHandle == regionHandle) { - if (s.RegionInfo.RegionHandle == regionHandle) - { - //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); - return s.IncomingChildAgentDataUpdate(cAgentData); - //if (OnChildAgentUpdate != null) - // return OnChildAgentUpdate(cAgentData); - } + //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); + s.IncomingChildAgentDataUpdate(cAgentData); + return true; } } //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate"); return false; } + public bool SendReleaseAgent(ulong regionHandle, UUID id, string uri) + { + //uint x, y; + //Utils.LongToUInts(regionHandle, out x, out y); + //x = x / Constants.RegionSize; + //y = y / Constants.RegionSize; + //Console.WriteLine("\n >>> Local SendReleaseAgent " + x + "-" + y); + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == regionHandle) + { + //m_log.Debug("[LOCAL COMMS]: Found region to SendReleaseAgent"); + return s.IncomingReleaseAgent(id); + } + } + //m_log.Debug("[LOCAL COMMS]: region not found in SendReleaseAgent"); + return false; + } + + public bool SendCloseAgent(ulong regionHandle, UUID id) + { + //uint x, y; + //Utils.LongToUInts(regionHandle, out x, out y); + //x = x / Constants.RegionSize; + //y = y / Constants.RegionSize; + //Console.WriteLine("\n >>> Local SendCloseAgent " + x + "-" + y); + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == regionHandle) + { + //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent"); + return s.IncomingCloseAgent(id); + } + } + //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); + return false; + } + #endregion /* IInterregionComms */ } } diff --git a/OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs b/OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs index b7c9269..f48e474 100644 --- a/OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs +++ b/OpenSim/Region/Environment/Modules/Communications/REST/RESTInterregionComms.cs @@ -146,6 +146,40 @@ namespace OpenSim.Region.Environment.Modules.Communications.REST } + public bool SendReleaseAgent(ulong regionHandle, UUID id, string uri) + { + // Try local first + if (m_localBackend.SendReleaseAgent(regionHandle, id, uri)) + return true; + + // else do the remote thing + return DoReleaseAgentCall(regionHandle, id, uri); + } + + public bool SendCloseAgent(ulong regionHandle, UUID id) + { + // Try local first + if (m_localBackend.SendCloseAgent(regionHandle, id)) + return true; + + // else do the remote thing + RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + return DoCloseAgentCall(regInfo, id); + } + //else + // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); + return false; + } + + #endregion /* IInterregionComms */ + + #region DoWork functions for the above public interface + //------------------------------------------------------------------- + // Internal functions for the above public interface + //------------------------------------------------------------------- + protected bool DoChildAgentUpdateCall(RegionInfo region, AgentData cAgentData) { // Eventually, we want to use a caps url instead of the agentID @@ -168,7 +202,7 @@ namespace OpenSim.Region.Environment.Modules.Communications.REST m_log.Debug("[REST COMMS]: PackUpdateMessage failed with exception: " + e.Message); } // Add the regionhandle of the destination region - ulong regionHandle = GetRegionHandle(region); + ulong regionHandle = GetRegionHandle(region.RegionHandle); args["destination_handle"] = OSD.FromString(regionHandle.ToString()); string strBuffer = ""; @@ -231,9 +265,77 @@ namespace OpenSim.Region.Environment.Modules.Communications.REST } - #endregion /* IInterregionComms */ + protected bool DoReleaseAgentCall(ulong regionHandle, UUID id, string uri) + { + //Console.WriteLine(" >>> DoReleaseAgentCall <<< " + uri); + + WebRequest request = WebRequest.Create(uri); + request.Method = "DELETE"; + request.Timeout = 10000; + + try + { + WebResponse webResponse = request.GetResponse(); + if (webResponse == null) + { + m_log.Info("[REST COMMS]: Null reply on agent get "); + } + + StreamReader sr = new StreamReader(webResponse.GetResponseStream()); + //reply = sr.ReadToEnd().Trim(); + sr.ReadToEnd().Trim(); + sr.Close(); + //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply); + + } + catch (WebException ex) + { + m_log.InfoFormat("[REST COMMS]: exception on reply of agent get {0}", ex.Message); + // ignore, really + } + + return true; + + } + + protected bool DoCloseAgentCall(RegionInfo region, UUID id) + { + string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + id + "/" + region.RegionHandle.ToString() +"/"; + + //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri); - #region Called from remote instances on this instance + WebRequest request = WebRequest.Create(uri); + request.Method = "DELETE"; + request.Timeout = 10000; + + try + { + WebResponse webResponse = request.GetResponse(); + if (webResponse == null) + { + m_log.Info("[REST COMMS]: Null reply on agent get "); + } + + StreamReader sr = new StreamReader(webResponse.GetResponseStream()); + //reply = sr.ReadToEnd().Trim(); + sr.ReadToEnd().Trim(); + sr.Close(); + //m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply); + + } + catch (WebException ex) + { + m_log.InfoFormat("[REST COMMS]: exception on reply of agent get {0}", ex.Message); + // ignore, really + } + + return true; + + } + + #endregion /* DoWork */ + + #region Incoming calls from remote instances public Hashtable AgentHandler(Hashtable request) { @@ -250,7 +352,8 @@ namespace OpenSim.Region.Environment.Modules.Communications.REST UUID agentID; string action; - if (!GetParams((string)request["uri"], out agentID, out action)) + ulong regionHandle; + if (!GetParams((string)request["uri"], out agentID, out regionHandle, out action)) { m_log.InfoFormat("[REST COMMS]: Invalid parameters for agent message {0}", request["uri"]); responsedata["int_response_code"] = 404; @@ -274,11 +377,9 @@ namespace OpenSim.Region.Environment.Modules.Communications.REST return responsedata; } - else if (method.Equals("GET")) + else if (method.Equals("DELETE")) { - m_log.InfoFormat("[REST COMMS]: method {0} not implemented yet in agent message", method); - responsedata["int_response_code"] = 404; - responsedata["str_response_string"] = "false"; + DoDelete(request, responsedata, agentID, action, regionHandle); return responsedata; } @@ -293,7 +394,7 @@ namespace OpenSim.Region.Environment.Modules.Communications.REST } - protected virtual void DoPut(Hashtable request, Hashtable responsedata) + protected OSDMap GetOSDMap(Hashtable request) { OSDMap args = null; try @@ -302,20 +403,32 @@ namespace OpenSim.Region.Environment.Modules.Communications.REST // We should pay attention to the content-type, but let's assume we know it's Json buffer = OSDParser.DeserializeJson((string)request["body"]); if (buffer.Type == OSDType.Map) + { args = (OSDMap)buffer; + return args; + } else { // uh? m_log.Debug("[REST COMMS]: Got OSD of type " + buffer.Type.ToString()); + return null; } } catch (Exception ex) { m_log.InfoFormat("[REST COMMS]: exception on parse of ChildAgentUpdate message {0}", ex.Message); + return null; + } + } + + protected virtual void DoPut(Hashtable request, Hashtable responsedata) + { + OSDMap args = GetOSDMap(request); + if (args == null) + { responsedata["int_response_code"] = 400; responsedata["str_response_string"] = "false"; - - return ; + return; } // retrieve the regionhandle @@ -343,19 +456,34 @@ namespace OpenSim.Region.Environment.Modules.Communications.REST responsedata["str_response_string"] = result.ToString(); } + protected virtual void DoDelete(Hashtable request, Hashtable responsedata, UUID id, string action, ulong regionHandle) + { + //Console.WriteLine(" >>> DoDelete action:" + action + "; regionHandle:" + regionHandle); + bool result = true; + if (action.Equals("release")) + { + result = m_localBackend.SendReleaseAgent(regionHandle, id, ""); + } + else + result = m_localBackend.SendCloseAgent(regionHandle, id); + + responsedata["int_response_code"] = 200; + responsedata["str_response_string"] = "OpenSim agent " + id.ToString(); + } #endregion #region Misc /// /// Extract the param from an uri. /// - /// Something like this: /agent/uuid/ or /agent/uuid/release + /// Something like this: /agent/uuid/ or /agent/uuid/handle/release /// uuid on uuid field /// optional action - protected bool GetParams(string uri, out UUID uuid, out string action) + protected bool GetParams(string uri, out UUID uuid, out ulong regionHandle, out string action) { uuid = UUID.Zero; action = ""; + regionHandle = 0; uri = uri.Trim(new char[] { '/' }); string[] parts = uri.Split('/'); @@ -369,20 +497,29 @@ namespace OpenSim.Region.Environment.Modules.Communications.REST return false; if (parts.Length >= 3) - action = parts[2]; - + UInt64.TryParse(parts[2], out regionHandle); + if (parts.Length >= 4) + action = parts[3]; + return true; } } - protected virtual ulong GetRegionHandle(RegionInfo region) + protected virtual ulong GetRegionHandle(ulong handle) { if (m_aScene.SceneGridService is HGSceneCommunicationService) - return ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.FindRegionHandle(region.RegionHandle); + return ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.FindRegionHandle(handle); - return region.RegionHandle; + return handle; } + protected virtual bool IsHyperlink(ulong handle) + { + if (m_aScene.SceneGridService is HGSceneCommunicationService) + return ((HGSceneCommunicationService)(m_aScene.SceneGridService)).m_hg.IsHyperlinkRegion(handle); + + return false; + } #endregion /* Misc */ } 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