From fd64823466ee667d0d827f95d3001ec8675512b2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 18 Jan 2010 10:37:11 -0800 Subject: [PATCH] * Added missing GatekeeperServiceConnector * Added basic machinery for teleporting users home. Untested. --- .../EntityTransfer/EntityTransferModule.cs | 454 +++++++++--------- .../EntityTransfer/HGEntityTransferModule.cs | 49 ++ .../Hypergrid/GatekeeperServerConnector.cs | 1 + .../Handlers/Hypergrid/HypergridHandlers.cs | 33 ++ .../Hypergrid/GatekeeperServiceConnector.cs | 119 +++++ .../HypergridService/GatekeeperService.cs | 38 +- .../HypergridService/HypergridService.cs | 8 +- .../Services/Interfaces/IGatekeeperService.cs | 3 + 8 files changed, 477 insertions(+), 228 deletions(-) create mode 100644 OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index fcc7a85d04..e85f270343 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -183,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); sp.Teleport(position); } - else + else // Another region possibly in another simulator { uint x = 0, y = 0; Utils.LongToUInts(regionHandle, out x, out y); @@ -191,15 +191,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (reg != null) { - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation to {0} in {1}", - position, reg.RegionName); - - uint newRegionX = (uint)(reg.RegionHandle >> 40); - uint newRegionY = (((uint)(reg.RegionHandle)) >> 8); - uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40); - uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8); - GridRegion finalDestination = GetFinalDestination(reg); if (finalDestination == null) { @@ -207,220 +198,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.ControllingClient.SendTeleportFailed("Problem at destination"); return; } - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is x={0} y={1} uuid={2}", finalDestination.RegionLocX, finalDestination.RegionLocY, finalDestination.RegionID); - ulong destinationHandle = finalDestination.RegionHandle; + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is x={0} y={1} uuid={2}", + finalDestination.RegionLocX / Constants.RegionSize, finalDestination.RegionLocY / Constants.RegionSize, finalDestination.RegionID); - if (eq == null) - sp.ControllingClient.SendTeleportLocationStart(); - - // Let's do DNS resolution only once in this process, please! - // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, - // it's actually doing a lot of work. - IPEndPoint endPoint = finalDestination.ExternalEndPoint; - if (endPoint.Address == null) - { - // Couldn't resolve the name. Can't TP, because the viewer wants IP addresses. - destRegionUp = false; - } - - if (destRegionUp) - { - // Fixing a bug where teleporting while sitting results in the avatar ending up removed from - // both regions - if (sp.ParentID != (uint)0) - sp.StandUp(); - - if (!sp.ValidateAttachments()) - { - sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state"); - return; - } - - // the avatar.Close below will clear the child region list. We need this below for (possibly) - // closing the child agents, so save it here (we need a copy as it is Clear()-ed). - //List childRegions = new List(avatar.GetKnownRegionList()); - // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport - // failure at this point (unlike a border crossing failure). So perhaps this can never fail - // once we reach here... - //avatar.Scene.RemoveCapsHandler(avatar.UUID); - - string capsPath = String.Empty; - - AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); - AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo(); - agentCircuit.startpos = position; - agentCircuit.child = true; - agentCircuit.Appearance = sp.Appearance; - if (currentAgentCircuit != null) - agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs; - - if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY)) - { - // brand new agent, let's create a new caps seed - agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); - } - - string reason = String.Empty; - - // Let's create an agent there if one doesn't exist yet. - if (!CreateAgent(reg, finalDestination, agentCircuit, teleportFlags, out reason)) - { - sp.ControllingClient.SendTeleportFailed(String.Format("Destination refused: {0}", - reason)); - return; - } - - // OK, it got this agent. Let's close some child agents - sp.CloseChildAgents(newRegionX, newRegionY); - - if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY)) - { - #region IP Translation for NAT - IClientIPEndpoint ipepClient; - if (sp.ClientView.TryGet(out ipepClient)) - { - capsPath - = "http://" - + NetworkUtil.GetHostFor(ipepClient.EndPoint, finalDestination.ExternalHostName) - + ":" - + finalDestination.HttpPort - + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); - } - else - { - capsPath - = "http://" - + finalDestination.ExternalHostName - + ":" - + finalDestination.HttpPort - + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); - } - #endregion - - if (eq != null) - { - #region IP Translation for NAT - // Uses ipepClient above - if (sp.ClientView.TryGet(out ipepClient)) - { - endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); - } - #endregion - - eq.EnableSimulator(destinationHandle, endPoint, sp.UUID); - - // ES makes the client send a UseCircuitCode message to the destination, - // which triggers a bunch of things there. - // So let's wait - Thread.Sleep(2000); - - eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); - - } - else - { - sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); - } - } - else - { - agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); - capsPath = "http://" + finalDestination.ExternalHostName + ":" + finalDestination.HttpPort - + "/CAPS/" + agentCircuit.CapsPath + "0000/"; - } - - // Expect avatar crossing is a heavy-duty function at the destination. - // That is where MakeRoot is called, which fetches appearance and inventory. - // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates. - //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId, - // position, false); - - //{ - // avatar.ControllingClient.SendTeleportFailed("Problem with destination."); - // // We should close that agent we just created over at destination... - // List lst = new List(); - // lst.Add(reg.RegionHandle); - // SendCloseChildAgentAsync(avatar.UUID, lst); - // return; - //} - - SetInTransit(sp.UUID); - - // Let's send a full update of the agent. This is a synchronous call. - AgentData agent = new AgentData(); - sp.CopyTo(agent); - agent.Position = position; - SetCallbackURL(agent, sp.Scene.RegionInfo); - - UpdateAgent(reg, finalDestination, agent); - - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, sp.UUID); - - - if (eq != null) - { - eq.TeleportFinishEvent(destinationHandle, 13, endPoint, - 0, teleportFlags, capsPath, sp.UUID); - } - else - { - sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4, - 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(sp.UUID)) - { - // Client never contacted destination. Let's restore everything back - sp.ControllingClient.SendTeleportFailed("Problems connecting to destination."); - - ResetFromTransit(sp.UUID); - - // Yikes! We should just have a ref to scene here. - //sp.Scene.InformClientOfNeighbours(sp); - EnableChildAgents(sp); - - // Finally, kill the agent we just created at the destination. - m_aScene.SimulationService.CloseAgent(finalDestination, sp.UUID); - - return; - } - - KillEntity(sp.Scene, sp.LocalId); - - sp.MakeChildAgent(); - - // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it - CrossAttachmentsIntoNewRegion(finalDestination, sp, true); - - // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone - - if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) - { - Thread.Sleep(5000); - sp.Close(); - sp.Scene.IncomingCloseAgent(sp.UUID); - } - else - // now we have a child agent in this region. - sp.Reset(); - - - // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! - if (sp.Scene.NeedSceneCacheClear(sp.UUID)) - { - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", - sp.UUID); - } - } - else - { - sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); - } + // + // This is it + // + DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags, eq); + // + // + // } else { @@ -450,6 +237,227 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } + protected void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq) + { + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation to {0} in {1}", + position, reg.RegionName); + + uint newRegionX = (uint)(reg.RegionHandle >> 40); + uint newRegionY = (((uint)(reg.RegionHandle)) >> 8); + uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40); + uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8); + + ulong destinationHandle = finalDestination.RegionHandle; + + if (eq == null) + sp.ControllingClient.SendTeleportLocationStart(); + + // Let's do DNS resolution only once in this process, please! + // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, + // it's actually doing a lot of work. + IPEndPoint endPoint = finalDestination.ExternalEndPoint; + if (endPoint.Address != null) + { + // Fixing a bug where teleporting while sitting results in the avatar ending up removed from + // both regions + if (sp.ParentID != (uint)0) + sp.StandUp(); + + if (!sp.ValidateAttachments()) + { + sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state"); + return; + } + + // the avatar.Close below will clear the child region list. We need this below for (possibly) + // closing the child agents, so save it here (we need a copy as it is Clear()-ed). + //List childRegions = new List(avatar.GetKnownRegionList()); + // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport + // failure at this point (unlike a border crossing failure). So perhaps this can never fail + // once we reach here... + //avatar.Scene.RemoveCapsHandler(avatar.UUID); + + string capsPath = String.Empty; + + AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); + AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo(); + agentCircuit.startpos = position; + agentCircuit.child = true; + agentCircuit.Appearance = sp.Appearance; + if (currentAgentCircuit != null) + agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs; + + if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY)) + { + // brand new agent, let's create a new caps seed + agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); + } + + string reason = String.Empty; + + // Let's create an agent there if one doesn't exist yet. + if (!CreateAgent(reg, finalDestination, agentCircuit, teleportFlags, out reason)) + { + sp.ControllingClient.SendTeleportFailed(String.Format("Destination refused: {0}", + reason)); + return; + } + + // OK, it got this agent. Let's close some child agents + sp.CloseChildAgents(newRegionX, newRegionY); + + if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY)) + { + #region IP Translation for NAT + IClientIPEndpoint ipepClient; + if (sp.ClientView.TryGet(out ipepClient)) + { + capsPath + = "http://" + + NetworkUtil.GetHostFor(ipepClient.EndPoint, finalDestination.ExternalHostName) + + ":" + + finalDestination.HttpPort + + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + } + else + { + capsPath + = "http://" + + finalDestination.ExternalHostName + + ":" + + finalDestination.HttpPort + + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + } + #endregion + + if (eq != null) + { + #region IP Translation for NAT + // Uses ipepClient above + if (sp.ClientView.TryGet(out ipepClient)) + { + endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); + } + #endregion + + eq.EnableSimulator(destinationHandle, endPoint, sp.UUID); + + // ES makes the client send a UseCircuitCode message to the destination, + // which triggers a bunch of things there. + // So let's wait + Thread.Sleep(2000); + + eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); + + } + else + { + sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); + } + } + else + { + agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); + capsPath = "http://" + finalDestination.ExternalHostName + ":" + finalDestination.HttpPort + + "/CAPS/" + agentCircuit.CapsPath + "0000/"; + } + + // Expect avatar crossing is a heavy-duty function at the destination. + // That is where MakeRoot is called, which fetches appearance and inventory. + // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates. + //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId, + // position, false); + + //{ + // avatar.ControllingClient.SendTeleportFailed("Problem with destination."); + // // We should close that agent we just created over at destination... + // List lst = new List(); + // lst.Add(reg.RegionHandle); + // SendCloseChildAgentAsync(avatar.UUID, lst); + // return; + //} + + SetInTransit(sp.UUID); + + // Let's send a full update of the agent. This is a synchronous call. + AgentData agent = new AgentData(); + sp.CopyTo(agent); + agent.Position = position; + SetCallbackURL(agent, sp.Scene.RegionInfo); + + UpdateAgent(reg, finalDestination, agent); + + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, sp.UUID); + + + if (eq != null) + { + eq.TeleportFinishEvent(destinationHandle, 13, endPoint, + 0, teleportFlags, capsPath, sp.UUID); + } + else + { + sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4, + 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(sp.UUID)) + { + // Client never contacted destination. Let's restore everything back + sp.ControllingClient.SendTeleportFailed("Problems connecting to destination."); + + ResetFromTransit(sp.UUID); + + // Yikes! We should just have a ref to scene here. + //sp.Scene.InformClientOfNeighbours(sp); + EnableChildAgents(sp); + + // Finally, kill the agent we just created at the destination. + m_aScene.SimulationService.CloseAgent(finalDestination, sp.UUID); + + return; + } + + KillEntity(sp.Scene, sp.LocalId); + + sp.MakeChildAgent(); + + // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it + CrossAttachmentsIntoNewRegion(finalDestination, sp, true); + + // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone + + if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) + { + Thread.Sleep(5000); + sp.Close(); + sp.Scene.IncomingCloseAgent(sp.UUID); + } + else + // now we have a child agent in this region. + sp.Reset(); + + + // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! + if (sp.Scene.NeedSceneCacheClear(sp.UUID)) + { + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", + sp.UUID); + } + } + else + { + sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); + } + } + + protected virtual bool CreateAgent(GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason) { return m_aScene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason); diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 101aea0293..0e6323b22f 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -111,6 +111,55 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason); } + public override void TeleportHome(UUID id, IClientAPI client) + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName); + + // Let's find out if this is a foreign user or a local user + UserAccount account = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, id); + if (account != null) + { + // local grid user + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local"); + base.TeleportHome(id, client); + return; + } + + // Foreign user wants to go home + // + AgentCircuitData aCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); + if (aCircuit == null || (aCircuit != null && !aCircuit.ServiceURLs.ContainsKey("GatewayURI"))) + { + client.SendTeleportFailed("Your information has been lost"); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Unable to locate agent's gateway information"); + return; + } + + GridRegion homeGatekeeper = MakeRegion(aCircuit); + if (homeGatekeeper == null) + { + client.SendTeleportFailed("Your information has been lost"); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent's gateway information is malformed"); + return; + } + + Vector3 position = Vector3.UnitY, lookAt = Vector3.UnitY; + GridRegion finalDestination = m_GatekeeperConnector.GetHomeRegion(homeGatekeeper, aCircuit.AgentID, out position, out lookAt); + } #endregion + + private GridRegion MakeRegion(AgentCircuitData aCircuit) + { + GridRegion region = new GridRegion(); + + Uri uri = null; + if (!Uri.TryCreate(aCircuit.ServiceURLs["GatewayURI"].ToString(), UriKind.Absolute, out uri)) + return null; + + region.ExternalHostName = uri.Host; + region.HttpPort = (uint)uri.Port; + region.RegionName = string.Empty; + return region; + } } } diff --git a/OpenSim/Server/Handlers/Hypergrid/GatekeeperServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/GatekeeperServerConnector.cs index c56ea3fcb3..f03d33a97e 100644 --- a/OpenSim/Server/Handlers/Hypergrid/GatekeeperServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/GatekeeperServerConnector.cs @@ -63,6 +63,7 @@ namespace OpenSim.Server.Handlers.Hypergrid HypergridHandlers hghandlers = new HypergridHandlers(m_GatekeeperService); server.AddXmlRPCHandler("link_region", hghandlers.LinkRegionRequest, false); server.AddXmlRPCHandler("get_region", hghandlers.GetRegion, false); + server.AddXmlRPCHandler("get_home_region", hghandlers.GetHomeRegion, false); server.AddHTTPHandler("/foreignagent/", new AgentHandler(m_GatekeeperService).Handler); diff --git a/OpenSim/Server/Handlers/Hypergrid/HypergridHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HypergridHandlers.cs index baafd7d3a4..846d1c2f18 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HypergridHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HypergridHandlers.cs @@ -111,5 +111,38 @@ namespace OpenSim.Server.Handlers.Hypergrid } + public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + Vector3 position = Vector3.UnitY, lookAt = Vector3.UnitY; + GridRegion regInfo = m_GatekeeperService.GetHomeRegion(userID, out position, out lookAt); + + Hashtable hash = new Hashtable(); + if (regInfo == null) + hash["result"] = "false"; + else + { + hash["result"] = "true"; + hash["uuid"] = regInfo.RegionID.ToString(); + hash["x"] = regInfo.RegionLocX.ToString(); + hash["y"] = regInfo.RegionLocY.ToString(); + hash["region_name"] = regInfo.RegionName; + hash["hostname"] = regInfo.ExternalHostName; + hash["http_port"] = regInfo.HttpPort.ToString(); + hash["internal_port"] = regInfo.InternalEndPoint.Port.ToString(); + hash["position"] = position.ToString(); + hash["lookAt"] = lookAt.ToString(); + } + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } } } diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs new file mode 100644 index 0000000000..a8d92920c5 --- /dev/null +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; + +using OpenSim.Services.Interfaces; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +using OpenMetaverse; +using Nwc.XmlRpc; + +using OpenSim.Services.Connectors.Simulation; + +namespace OpenSim.Services.Connectors.Hypergrid +{ + public class GatekeeperServiceConnector : SimulationServiceConnector + { + protected override string AgentPath() + { + return "/foreignagent/"; + } + + protected override string ObjectPath() + { + return "/foreignobject/"; + } + + public GridRegion GetHomeRegion(GridRegion gatekeeper, UUID userID, out Vector3 position, out Vector3 lookAt) + { + position = Vector3.UnitY; lookAt = Vector3.UnitY; + + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("get_home_region", paramList); + string uri = "http://" + gatekeeper.ExternalHostName + ":" + gatekeeper.HttpPort + "/"; + XmlRpcResponse response = null; + try + { + response = request.Send(uri, 10000); + } + catch (Exception e) + { + return null; + } + + if (response.IsFault) + { + return null; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + bool success = false; + Boolean.TryParse((string)hash["result"], out success); + if (success) + { + GridRegion region = new GridRegion(); + + UUID.TryParse((string)hash["uuid"], out region.RegionID); + //m_log.Debug(">> HERE, uuid: " + region.RegionID); + int n = 0; + if (hash["x"] != null) + { + Int32.TryParse((string)hash["x"], out n); + region.RegionLocX = n; + //m_log.Debug(">> HERE, x: " + region.RegionLocX); + } + if (hash["y"] != null) + { + Int32.TryParse((string)hash["y"], out n); + region.RegionLocY = n; + //m_log.Debug(">> HERE, y: " + region.RegionLocY); + } + if (hash["region_name"] != null) + { + region.RegionName = (string)hash["region_name"]; + //m_log.Debug(">> HERE, name: " + region.RegionName); + } + if (hash["hostname"] != null) + region.ExternalHostName = (string)hash["hostname"]; + if (hash["http_port"] != null) + { + uint p = 0; + UInt32.TryParse((string)hash["http_port"], out p); + region.HttpPort = p; + } + if (hash["internal_port"] != null) + { + int p = 0; + Int32.TryParse((string)hash["internal_port"], out p); + region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p); + } + if (hash["position"] != null) + Vector3.TryParse((string)hash["position"], out position); + if (hash["lookAt"] != null) + Vector3.TryParse((string)hash["lookAt"], out lookAt); + + // Successful return + return region; + } + + } + catch (Exception e) + { + return null; + } + + return null; + + } + } +} diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs index 72db93f368..55d9ce11d9 100644 --- a/OpenSim/Services/HypergridService/GatekeeperService.cs +++ b/OpenSim/Services/HypergridService/GatekeeperService.cs @@ -164,6 +164,7 @@ namespace OpenSim.Services.HypergridService return region; } + #region Login Agent public bool LoginAgent(AgentCircuitData aCircuit, GridRegion destination, out string reason) { reason = string.Empty; @@ -221,7 +222,7 @@ namespace OpenSim.Services.HypergridService return m_SimulationService.CreateAgent(destination, aCircuit, 0, out reason); } - protected bool Authenticate(AgentCircuitData aCircuit) + protected bool Authenticate(AgentCircuitData aCircuit) { string authURL = string.Empty; if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) @@ -250,5 +251,40 @@ namespace OpenSim.Services.HypergridService return false; } + + #endregion + + public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt) + { + position = new Vector3(128, 128, 0); lookAt = Vector3.UnitY; + + m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to get home region of user {0}", userID); + + GridRegion home = null; + PresenceInfo[] presences = m_PresenceService.GetAgents(new string[] { userID.ToString() }); + if (presences != null && presences.Length > 0) + { + UUID homeID = presences[0].HomeRegionID; + if (homeID != UUID.Zero) + { + home = m_GridService.GetRegionByUUID(m_ScopeID, homeID); + position = presences[0].HomePosition; + lookAt = presences[0].HomeLookAt; + } + if (home == null) + { + List defs = m_GridService.GetDefaultRegions(m_ScopeID); + if (defs != null && defs.Count > 0) + home = defs[0]; + } + } + + return home; + } + + #region Misc + + + #endregion } } diff --git a/OpenSim/Services/HypergridService/HypergridService.cs b/OpenSim/Services/HypergridService/HypergridService.cs index 734931d29b..ac0f5ac1d9 100644 --- a/OpenSim/Services/HypergridService/HypergridService.cs +++ b/OpenSim/Services/HypergridService/HypergridService.cs @@ -51,7 +51,7 @@ namespace OpenSim.Services.HypergridService private static HypergridService m_RootInstance = null; protected IConfigSource m_config; - protected IAuthenticationService m_AuthenticationService = null; + protected IPresenceService m_PresenceService = null; protected IGridService m_GridService; protected IAssetService m_AssetService; protected HypergridServiceConnector m_HypergridConnector; @@ -94,7 +94,7 @@ namespace OpenSim.Services.HypergridService if (gridConfig != null) { string gridService = gridConfig.GetString("GridService", string.Empty); - string authService = gridConfig.GetString("AuthenticationService", String.Empty); + string presenceService = gridConfig.GetString("PresenceService", String.Empty); string assetService = gridConfig.GetString("AssetService", string.Empty); Object[] args = new Object[] { config }; @@ -104,8 +104,8 @@ namespace OpenSim.Services.HypergridService if (m_GridService == null) throw new Exception("HypergridService cannot function without a GridService"); - if (authService != String.Empty) - m_AuthenticationService = ServerUtils.LoadPlugin(authService, args); + if (presenceService != String.Empty) + m_PresenceService = ServerUtils.LoadPlugin(presenceService, args); if (assetService != string.Empty) m_AssetService = ServerUtils.LoadPlugin(assetService, args); diff --git a/OpenSim/Services/Interfaces/IGatekeeperService.cs b/OpenSim/Services/Interfaces/IGatekeeperService.cs index d41df759da..59e0f82702 100644 --- a/OpenSim/Services/Interfaces/IGatekeeperService.cs +++ b/OpenSim/Services/Interfaces/IGatekeeperService.cs @@ -39,5 +39,8 @@ namespace OpenSim.Services.Interfaces GridRegion GetHyperlinkRegion(UUID regionID); bool LoginAgent(AgentCircuitData aCircuit, GridRegion destination, out string reason); + + GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); + } }