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(-)
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