From 32ccc7a9d912543c0a5d3f8db839734194f3d8dd Mon Sep 17 00:00:00 2001 From: Jonathan Freedman Date: Sat, 2 Oct 2010 19:17:02 -0400 Subject: [PATCH 01/51] * refactor refactor refactor ServerURI 4 lyfe --- OpenSim/Framework/RegionInfo.cs | 8 +++- .../Servers/HttpServer/BaseHttpServer.cs | 10 ++--- OpenSim/Region/Application/OpenSimBase.cs | 2 +- .../EntityTransfer/EntityTransferModule.cs | 27 +++-------- .../World/WorldMap/WorldMapModule.cs | 2 +- .../Hypergrid/GatekeeperServiceConnector.cs | 31 ++++++++----- .../Connectors/Land/LandServiceConnector.cs | 3 +- .../Neighbour/NeighbourServiceConnector.cs | 2 +- .../SimianGrid/SimianGridServiceConnector.cs | 4 +- .../Simulation/SimulationServiceConnector.cs | 45 +++---------------- .../Services/GridService/HypergridLinker.cs | 14 +++++- .../HypergridService/GatekeeperService.cs | 2 +- .../HypergridService/UserAgentService.cs | 8 ++-- OpenSim/Services/Interfaces/IGridService.cs | 8 +++- 14 files changed, 72 insertions(+), 94 deletions(-) diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 08d5398a18..949a28985e 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -116,7 +116,13 @@ namespace OpenSim.Framework public string ServerURI { get { return m_serverURI; } - set { m_serverURI = value; } + set { + if ( value.EndsWith("/") ) { + m_serverURI = value; + } else { + m_serverURI = value + '/'; + } + } } protected string m_serverURI; diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 452df38d31..54e4a4611e 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -348,7 +348,7 @@ namespace OpenSim.Framework.Servers.HttpServer { try { -// m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); + m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); @@ -376,11 +376,11 @@ namespace OpenSim.Framework.Servers.HttpServer string path = request.RawUrl; string handlerKey = GetHandlerKey(request.HttpMethod, path); -// m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); + m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); if (TryGetStreamHandler(handlerKey, out requestHandler)) { - //m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); + m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler. byte[] buffer = null; @@ -395,7 +395,7 @@ namespace OpenSim.Framework.Servers.HttpServer } else if (requestHandler is IGenericHTTPHandler) { - //m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); + m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler; Stream requestStream = request.InputStream; @@ -422,7 +422,7 @@ namespace OpenSim.Framework.Servers.HttpServer foreach (string headername in rHeaders) { - //m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); + m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); headervals[headername] = request.Headers[headername]; } diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 74ad1685f9..f30a8504fe 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -327,8 +327,8 @@ namespace OpenSim //regionInfo.originRegionID = regionInfo.RegionID; // set initial ServerURI - regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.InternalEndPoint.Port; regionInfo.HttpPort = m_httpServerPort; + regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort.ToString(); regionInfo.osSecret = m_osSecret; diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 81f49b6710..828c4e7c01 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -333,20 +333,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (sp.ClientView.TryGet(out ipepClient)) { capsPath - = "http://" - + NetworkUtil.GetHostFor(ipepClient.EndPoint, finalDestination.ExternalHostName) - + ":" - + finalDestination.HttpPort - + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } else { - capsPath - = "http://" - + finalDestination.ExternalHostName - + ":" - + finalDestination.HttpPort - + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } #endregion @@ -378,8 +369,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer else { agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); - capsPath = "http://" + finalDestination.ExternalHostName + ":" + finalDestination.HttpPort - + "/CAPS/" + agentCircuit.CapsPath + "0000/"; + capsPath = finalDestination.ServerURI + "/CAPS/" + agentCircuit.CapsPath + "0000/"; } // Expect avatar crossing is a heavy-duty function at the destination. @@ -512,8 +502,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) { - agent.CallbackURI = "http://" + region.ExternalHostName + ":" + region.HttpPort + - "/agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; + agent.CallbackURI = region.ServerURI + "/agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; } @@ -838,7 +827,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer cAgent.Position = pos; if (isFlying) cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; - cAgent.CallbackURI = "http://" + m_scene.RegionInfo.ExternalHostName + ":" + m_scene.RegionInfo.HttpPort + + cAgent.CallbackURI = m_scene.RegionInfo.ServerURI + "/agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) @@ -866,8 +855,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } // TODO Should construct this behind a method string capsPath = - "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort - + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/"; + neighbourRegion.ServerURI + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/"; m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); @@ -1178,8 +1166,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer y = y / Constants.RegionSize; m_log.Info("[ENTITY TRANSFER MODULE]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")"); - string capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort - + "/CAPS/" + a.CapsPath + "0000/"; + string capsPath = reg.ServerURI + "/CAPS/" + a.CapsPath + "0000/"; string reason = String.Empty; diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index fbc8a50350..1b5f23ed51 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -147,7 +147,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString(); regionimage = regionimage.Replace("-", ""); - m_log.Info("[WORLD MAP]: JPEG Map location: http://" + m_scene.RegionInfo.ExternalEndPoint.Address.ToString() + ":" + m_scene.RegionInfo.HttpPort.ToString() + "/index.php?method=" + regionimage); + m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "/index.php?method=" + regionimage); MainServer.Instance.AddHTTPHandler(regionimage, OnHTTPGetMapImage); MainServer.Instance.AddLLSDHandler( diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 479a80e297..89a8f7a1b8 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -108,8 +108,8 @@ namespace OpenSim.Services.Connectors.Hypergrid } hash = (Hashtable)response.Value; - //foreach (Object o in hash) - // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + foreach (Object o in hash) + m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); try { bool success = false; @@ -117,16 +117,20 @@ namespace OpenSim.Services.Connectors.Hypergrid if (success) { UUID.TryParse((string)hash["uuid"], out regionID); - //m_log.Debug(">> HERE, uuid: " + uuid); + m_log.Debug(">> HERE, uuid: " + regionID); if ((string)hash["handle"] != null) { realHandle = Convert.ToUInt64((string)hash["handle"]); - //m_log.Debug(">> HERE, realHandle: " + realHandle); + m_log.Debug(">> HERE, realHandle: " + realHandle); } - if (hash["region_image"] != null) + if (hash["region_image"] != null) { imageURL = (string)hash["region_image"]; - if (hash["external_name"] != null) + m_log.Debug(">> HERE, imageURL: " + imageURL); + } + if (hash["external_name"] != null) { externalName = (string)hash["external_name"]; + m_log.Debug(">> HERE, externalName: " + externalName); + } } } @@ -208,8 +212,8 @@ namespace OpenSim.Services.Connectors.Hypergrid } hash = (Hashtable)response.Value; - //foreach (Object o in hash) - // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + foreach (Object o in hash) + m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); try { bool success = false; @@ -219,38 +223,41 @@ namespace OpenSim.Services.Connectors.Hypergrid GridRegion region = new GridRegion(); UUID.TryParse((string)hash["uuid"], out region.RegionID); - //m_log.Debug(">> HERE, uuid: " + 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); + 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); + 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); + m_log.Debug(">> HERE, region_name: " + region.RegionName); } if (hash["hostname"] != null) region.ExternalHostName = (string)hash["hostname"]; + m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); if (hash["http_port"] != null) { uint p = 0; UInt32.TryParse((string)hash["http_port"], out p); region.HttpPort = p; + m_log.Debug(">> HERE, http_port: " + region.HttpPort); } 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); + m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); } // Successful return diff --git a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs index 8143b5a89f..4b25ac819a 100644 --- a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs +++ b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs @@ -84,8 +84,7 @@ namespace OpenSim.Services.Connectors if (info != null) // just to be sure { XmlRpcRequest request = new XmlRpcRequest("land_data", paramList); - string uri = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"; - XmlRpcResponse response = request.Send(uri, 10000); + XmlRpcResponse response = request.Send(info.ServerURI, 10000); if (response.IsFault) { m_log.ErrorFormat("[LAND CONNECTOR]: remote call returned an error: {0}", response.FaultString); diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs index 0a982f8d57..9c57a40701 100644 --- a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs +++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs @@ -87,7 +87,7 @@ namespace OpenSim.Services.Connectors public bool DoHelloNeighbourCall(GridRegion region, RegionInfo thisRegion) { - string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/region/" + thisRegion.RegionID + "/"; + string uri = region.ServerURI + "/region/" + thisRegion.RegionID + "/"; //m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri); WebRequest HelloNeighbourRequest = WebRequest.Create(uri); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index 4409d5ce00..0a9f230601 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -145,8 +145,6 @@ namespace OpenSim.Services.Connectors.SimianGrid Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0); - string httpAddress = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort + "/"; - OSDMap extraData = new OSDMap { { "ServerURI", OSD.FromString(regionInfo.ServerURI) }, @@ -168,7 +166,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Name", regionInfo.RegionName }, { "MinPosition", minPosition.ToString() }, { "MaxPosition", maxPosition.ToString() }, - { "Address", httpAddress }, + { "Address", regionInfo.ServerURI }, { "Enabled", "1" }, { "ExtraData", OSDParser.SerializeJsonString(extraData) } }; diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index a5f748f0c4..07839d3b59 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -104,24 +104,7 @@ namespace OpenSim.Services.Connectors.Simulation return false; } - string uri = string.Empty; - - // HACK -- Simian grid make it work!!! - if (destination.ServerURI != null && destination.ServerURI != string.Empty && !destination.ServerURI.StartsWith("http:")) - uri = "http://" + destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; - else - { - try - { - uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + aCircuit.AgentID + "/"; - } - catch (Exception e) - { - m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent create. Reason: " + e.Message); - reason = e.Message; - return false; - } - } + string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri); @@ -277,16 +260,7 @@ namespace OpenSim.Services.Connectors.Simulation private bool UpdateAgent(GridRegion destination, IAgentData cAgentData) { // Eventually, we want to use a caps url instead of the agentID - string uri = string.Empty; - try - { - uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + cAgentData.AgentID + "/"; - } - catch (Exception e) - { - m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent update. Reason: " + e.Message); - return false; - } + string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; //Console.WriteLine(" >>> DoAgentUpdateCall <<< " + uri); HttpWebRequest ChildUpdateRequest = (HttpWebRequest)WebRequest.Create(uri); @@ -385,7 +359,7 @@ namespace OpenSim.Services.Connectors.Simulation { agent = null; // Eventually, we want to use a caps url instead of the agentID - string uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; //Console.WriteLine(" >>> DoRetrieveRootAgentCall <<< " + uri); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); @@ -479,16 +453,7 @@ namespace OpenSim.Services.Connectors.Simulation public bool CloseAgent(GridRegion destination, UUID id) { - string uri = string.Empty; - try - { - uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; - } - catch (Exception e) - { - m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent close. Reason: " + e.Message); - return false; - } + string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri); @@ -538,7 +503,7 @@ namespace OpenSim.Services.Connectors.Simulation public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall) { string uri - = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + ObjectPath() + sog.UUID + "/"; + = destination.ServerURI + ObjectPath() + sog.UUID + "/"; //m_log.Debug(" >>> DoCreateObjectCall <<< " + uri); WebRequest ObjectCreateRequest = WebRequest.Create(uri); diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index b86fb6f01c..757ae80a70 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -127,7 +127,7 @@ namespace OpenSim.Services.GridService if (MainConsole.Instance != null) { MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region", - "link-region :[:] ", + "link-region [] ", "Link a hypergrid region", RunCommand); MainConsole.Instance.Commands.AddCommand("hypergrid", false, "unlink-region", "unlink-region or : ", @@ -200,9 +200,15 @@ namespace OpenSim.Services.GridService } - // From the command line and the 2 above public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) + { + TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, regInfo, reason); + } + + // From the command line and the 2 above + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, + string externalRegionName, uint externalPort, string externalHostName, string serverURI, out GridRegion regInfo, out string reason) { m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0}:{1}:{2}, in {3}-{4}", externalHostName, externalPort, externalRegionName, xloc, yloc); @@ -509,12 +515,16 @@ namespace OpenSim.Services.GridService int xloc, yloc; uint externalPort; string externalHostName; + string serverURI; try { xloc = Convert.ToInt32(cmdparams[0]); yloc = Convert.ToInt32(cmdparams[1]); externalPort = Convert.ToUInt32(cmdparams[3]); externalHostName = cmdparams[2]; + if ( cmdparams.Length == 4 ) { + + } //internalPort = Convert.ToUInt32(cmdparams[4]); //remotingPort = Convert.ToUInt32(cmdparams[5]); } diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs index 3f5c4f1400..9e961636ce 100644 --- a/OpenSim/Services/HypergridService/GatekeeperService.cs +++ b/OpenSim/Services/HypergridService/GatekeeperService.cs @@ -157,7 +157,7 @@ namespace OpenSim.Services.HypergridService string regionimage = "regionImage" + region.RegionID.ToString(); regionimage = regionimage.Replace("-", ""); - imageURL = "http://" + region.ExternalHostName + ":" + region.HttpPort + "/index.php?method=" + regionimage; + imageURL = region.ServerURI + "index.php?method=" + regionimage; return true; } diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 8acd618b92..4653b31eae 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -145,13 +145,13 @@ namespace OpenSim.Services.HypergridService region.RegionLocY = finalDestination.RegionLocY; // Generate a new service session - agentCircuit.ServiceSessionID = "http://" + region.ExternalHostName + ":" + region.HttpPort + ";" + UUID.Random(); + agentCircuit.ServiceSessionID = region.ServerURI + ";" + UUID.Random(); TravelingAgentInfo old = UpdateTravelInfo(agentCircuit, region); //bool success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out reason); bool success = false; string myExternalIP = string.Empty; - string gridName = "http://" + gatekeeper.ExternalHostName + ":" + gatekeeper.HttpPort; + string gridName = gatekeeper.ServerURI; if (m_GridName == gridName) success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); else @@ -160,7 +160,7 @@ namespace OpenSim.Services.HypergridService if (!success) { m_log.DebugFormat("[USER AGENT SERVICE]: Unable to login user {0} {1} to grid {2}, reason: {3}", - agentCircuit.firstname, agentCircuit.lastname, region.ExternalHostName + ":" + region.HttpPort, reason); + agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason); // restore the old travel info lock (m_TravelingAgents) @@ -206,7 +206,7 @@ namespace OpenSim.Services.HypergridService m_TravelingAgents[agentCircuit.SessionID] = travel; } travel.UserID = agentCircuit.AgentID; - travel.GridExternalName = "http://" + region.ExternalHostName + ":" + region.HttpPort; + travel.GridExternalName = region.ServerURI; travel.ServiceToken = agentCircuit.ServiceSessionID; if (old != null) travel.ClientIPAddress = old.ClientIPAddress; diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index 77230a33d7..bf441e6076 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -116,7 +116,13 @@ namespace OpenSim.Services.Interfaces public string ServerURI { get { return m_serverURI; } - set { m_serverURI = value; } + set { + if ( value.EndsWith("/") ) { + m_serverURI = value; + } else { + m_serverURI = value + '/'; + } + } } protected string m_serverURI; From 69acf9c79b9e83047c2a0494a6f96c7d33839d3b Mon Sep 17 00:00:00 2001 From: Jonathan Freedman Date: Sun, 3 Oct 2010 18:03:53 -0400 Subject: [PATCH 02/51] * additional serveruri cleanup --- OpenSim/Region/Application/OpenSimBase.cs | 2 +- .../InstantMessage/MessageTransferModule.cs | 6 ++-- .../World/WorldMap/WorldMapModule.cs | 2 +- .../Hypergrid/GatekeeperServiceConnector.cs | 14 ++++----- .../Simulation/SimulationServiceConnector.cs | 10 +------ OpenSim/Services/GridService/GridService.cs | 2 +- .../Services/GridService/HypergridLinker.cs | 11 ++++--- .../LLLoginService/LLLoginResponse.cs | 29 +------------------ 8 files changed, 21 insertions(+), 55 deletions(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index f30a8504fe..904a50c799 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -328,7 +328,7 @@ namespace OpenSim // set initial ServerURI regionInfo.HttpPort = m_httpServerPort; - regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort.ToString(); + regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort.ToString() + "/"; regionInfo.osSecret = m_osSecret; diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 918fa04143..fdc48c6b69 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -599,7 +599,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage try { - XmlRpcResponse GridResp = GridReq.Send("http://" + reginfo.ExternalHostName + ":" + reginfo.HttpPort, 3000); + XmlRpcResponse GridResp = GridReq.Send(reginfo.ServerURI, 3000); Hashtable responseData = (Hashtable)GridResp.Value; @@ -621,8 +621,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } catch (WebException e) { - m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to http://{0}:{1} the host didn't respond ({2})", - reginfo.ExternalHostName, reginfo.HttpPort, e.Message); + m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0}} the host didn't respond ({2})", + reginfo.ServerURI, e.Message); } return false; diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 1b5f23ed51..71cf306695 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -579,7 +579,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (mreg != null) { - httpserver = "http://" + mreg.ExternalEndPoint.Address.ToString() + ":" + mreg.HttpPort + "/MAP/MapItems/" + regionhandle.ToString(); + httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString(); lock (m_cachedRegionMapItemsAddress) { if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 89a8f7a1b8..2b19b8709f 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -63,12 +63,12 @@ namespace OpenSim.Services.Connectors.Hypergrid protected override string AgentPath() { - return "/foreignagent/"; + return "foreignagent/"; } protected override string ObjectPath() { - return "/foreignobject/"; + return "foreignobject/"; } public bool LinkRegion(GridRegion info, out UUID regionID, out ulong realHandle, out string externalName, out string imageURL, out string reason) @@ -86,12 +86,11 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("link_region", paramList); - string uri = "http://" + ((info.ServerURI != null && info.ServerURI != string.Empty && !info.ServerURI.StartsWith("http:")) ? info.ServerURI : info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"); - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Linking to " + uri); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Linking to " + info.ServerURI); XmlRpcResponse response = null; try { - response = request.Send(uri, 10000); + response = request.Send(info.ServerURI, 10000); } catch (Exception e) { @@ -192,12 +191,11 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_region", paramList); - string uri = "http://" + ((gatekeeper.ServerURI != null && gatekeeper.ServerURI != string.Empty && !gatekeeper.ServerURI.StartsWith("http:")) ? gatekeeper.ServerURI : gatekeeper.ExternalEndPoint.Address + ":" + gatekeeper.HttpPort + "/"); - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + uri); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); XmlRpcResponse response = null; try { - response = request.Send(uri, 10000); + response = request.Send(gatekeeper.ServerURI, 10000); } catch (Exception e) { diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 07839d3b59..c4284eb920 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -72,7 +72,7 @@ namespace OpenSim.Services.Connectors.Simulation protected virtual string AgentPath() { - return "/agent/"; + return "agent/"; } public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) @@ -106,8 +106,6 @@ namespace OpenSim.Services.Connectors.Simulation string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; - //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri); - AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri); AgentCreateRequest.Method = "POST"; AgentCreateRequest.ContentType = "application/json"; @@ -261,7 +259,6 @@ namespace OpenSim.Services.Connectors.Simulation { // Eventually, we want to use a caps url instead of the agentID string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; - //Console.WriteLine(" >>> DoAgentUpdateCall <<< " + uri); HttpWebRequest ChildUpdateRequest = (HttpWebRequest)WebRequest.Create(uri); ChildUpdateRequest.Method = "PUT"; @@ -360,7 +357,6 @@ namespace OpenSim.Services.Connectors.Simulation agent = null; // Eventually, we want to use a caps url instead of the agentID string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; - //Console.WriteLine(" >>> DoRetrieveRootAgentCall <<< " + uri); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "GET"; @@ -381,7 +377,6 @@ namespace OpenSim.Services.Connectors.Simulation sr = new StreamReader(webResponse.GetResponseStream()); reply = sr.ReadToEnd().Trim(); - //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: ChilAgentUpdate reply was " + reply); } catch (WebException ex) @@ -402,7 +397,6 @@ namespace OpenSim.Services.Connectors.Simulation OSDMap args = Util.GetOSDMap(reply); if (args == null) { - //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: Error getting OSDMap from reply"); return false; } @@ -411,7 +405,6 @@ namespace OpenSim.Services.Connectors.Simulation return true; } - //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: DoRetrieveRootAgentCall returned status " + webResponse.StatusCode); return false; } @@ -455,7 +448,6 @@ namespace OpenSim.Services.Connectors.Simulation { string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; - //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri); WebRequest request = WebRequest.Create(uri); request.Method = "DELETE"; diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index ce6f64b422..add1be0b49 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -479,7 +479,7 @@ namespace OpenSim.Services.GridService OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); MainConsole.Instance.Output(String.Format("{0,-20} {1}\n{2,-20} {3}\n{4,-39} {5}\n\n", r.RegionName, r.RegionID, - String.Format("{0},{1}", r.posX, r.posY), "http://" + r.Data["serverIP"].ToString() + ":" + r.Data["serverPort"].ToString(), + String.Format("{0},{1}", r.posX, r.posY), r.Data["serverURI"], r.Data["owner_uuid"].ToString(), flags.ToString())); } return; diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 757ae80a70..11df7e0b73 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -199,11 +199,14 @@ namespace OpenSim.Services.GridService return null; } - - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, - string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, string serverURI, out GridRegion regInfo, out string reason) { - TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, regInfo, reason); + return TryCreateLink(scopeID, xloc, yloc, externalRegionName, 0, null, serverURI, out regInfo, out reason); + } + + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) + { + return TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, out regInfo, out reason); } // From the command line and the 2 above diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index 0da1715849..f985ab21ba 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -333,34 +333,7 @@ namespace OpenSim.Services.LLLoginService private void FillOutSeedCap(AgentCircuitData aCircuit, GridRegion destination, IPEndPoint ipepClient) { - string capsSeedPath = String.Empty; - - // Don't use the following! It Fails for logging into any region not on the same port as the http server! - // Kept here so it doesn't happen again! - // response.SeedCapability = regionInfo.ServerURI + capsSeedPath; - - #region IP Translation for NAT - if (ipepClient != null) - { - capsSeedPath - = "http://" - + NetworkUtil.GetHostFor(ipepClient.Address, destination.ExternalHostName) - + ":" - + destination.HttpPort - + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); - } - else - { - capsSeedPath - = "http://" - + destination.ExternalHostName - + ":" - + destination.HttpPort - + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); - } - #endregion - - SeedCapability = capsSeedPath; + SeedCapability = destination.ServerURI + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); } private void SetDefaultValues() From a2167b0f0dfef5f8aeb7bee99f34f672f6004bb3 Mon Sep 17 00:00:00 2001 From: Jonathan Freedman Date: Mon, 11 Oct 2010 16:53:00 -0400 Subject: [PATCH 03/51] * more url / hg cleanup --- OpenSim/Framework/Capabilities/CapsUtil.cs | 2 +- OpenSim/Framework/RegionInfo.cs | 31 +++++++++++++++-- .../EntityTransfer/EntityTransferModule.cs | 34 ++++++------------- .../InterGrid/OpenGridProtocolModule.cs | 4 +-- .../Handlers/Hypergrid/HomeAgentHandlers.cs | 2 ++ .../Services/GridService/HypergridLinker.cs | 18 +++------- .../HypergridService/UserAgentService.cs | 1 + OpenSim/Services/Interfaces/IGridService.cs | 9 ++++- 8 files changed, 56 insertions(+), 45 deletions(-) diff --git a/OpenSim/Framework/Capabilities/CapsUtil.cs b/OpenSim/Framework/Capabilities/CapsUtil.cs index 0334e4b4a2..faf2708541 100644 --- a/OpenSim/Framework/Capabilities/CapsUtil.cs +++ b/OpenSim/Framework/Capabilities/CapsUtil.cs @@ -41,7 +41,7 @@ namespace OpenSim.Framework.Capabilities /// public static string GetCapsSeedPath(string capsObjectPath) { - return "/CAPS/" + capsObjectPath + "0000/"; + return "CAPS/" + capsObjectPath + "0000/"; } /// diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 949a28985e..73b8bd0120 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -115,7 +115,13 @@ namespace OpenSim.Framework /// public string ServerURI { - get { return m_serverURI; } + get { + if ( m_serverURI != string.Empty ) { + return m_serverURI; + } else { + return "http://" + m_externalHostName + ":" + m_httpPort + "/"; + } + } set { if ( value.EndsWith("/") ) { m_serverURI = value; @@ -147,6 +153,7 @@ namespace OpenSim.Framework public SimpleRegionInfo() { + m_serverURI = string.Empty; } public SimpleRegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) @@ -156,6 +163,7 @@ namespace OpenSim.Framework m_internalEndPoint = internalEndPoint; m_externalHostName = externalUri; + m_serverURI = string.Empty; } public SimpleRegionInfo(uint regionLocX, uint regionLocY, string externalUri, uint port) @@ -166,6 +174,7 @@ namespace OpenSim.Framework m_externalHostName = externalUri; m_internalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int) port); + m_serverURI = string.Empty; } public SimpleRegionInfo(RegionInfo ConvertFrom) @@ -455,6 +464,7 @@ namespace OpenSim.Framework configMember = new ConfigurationMember(xmlNode, description, loadConfigurationOptions, handleIncomingConfiguration, !skipConsoleConfig); configMember.performConfigurationRetrieve(); + m_serverURI = string.Empty; } public RegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) @@ -464,10 +474,12 @@ namespace OpenSim.Framework m_internalEndPoint = internalEndPoint; m_externalHostName = externalUri; + m_serverURI = string.Empty; } public RegionInfo() { + m_serverURI = string.Empty; } public EstateSettings EstateSettings @@ -557,10 +569,23 @@ namespace OpenSim.Framework /// /// A well-formed URI for the host region server (namely "http://" + ExternalHostName) /// + public string ServerURI { - get { return m_serverURI; } - set { m_serverURI = value; } + get { + if ( m_serverURI != string.Empty ) { + return m_serverURI; + } else { + return "http://" + m_externalHostName + ":" + m_httpPort + "/"; + } + } + set { + if ( value.EndsWith("/") ) { + m_serverURI = value; + } else { + m_serverURI = value + '/'; + } + } } public string RegionName diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 3791e1df6f..54cc80f384 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -327,34 +327,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // OK, it got this agent. Let's close some child agents sp.CloseChildAgents(newRegionX, newRegionY); - + IClientIPEndpoint ipepClient; if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY)) { //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); - #region IP Translation for NAT - IClientIPEndpoint ipepClient; + // Uses ipepClient above if (sp.ClientView.TryGet(out ipepClient)) { - capsPath - = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); - } - else - { - capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); } #endregion + capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); 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, @@ -373,7 +360,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer else { agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); - capsPath = finalDestination.ServerURI + "/CAPS/" + agentCircuit.CapsPath + "0000/"; + capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } // Expect avatar crossing is a heavy-duty function at the destination. @@ -506,7 +493,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) { - agent.CallbackURI = region.ServerURI + "/agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; + agent.CallbackURI = region.ServerURI + "agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; + m_log.Debug("Set callback URL to " + agent.CallbackURI); } @@ -832,7 +820,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (isFlying) cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; cAgent.CallbackURI = m_scene.RegionInfo.ServerURI + - "/agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; + "agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) { @@ -857,9 +845,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer neighbourRegion.RegionHandle); return agent; } - // TODO Should construct this behind a method - string capsPath = - neighbourRegion.ServerURI + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/"; + string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); @@ -1178,7 +1164,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer y = y / Constants.RegionSize; m_log.Info("[ENTITY TRANSFER MODULE]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")"); - string capsPath = reg.ServerURI + "/CAPS/" + a.CapsPath + "0000/"; + string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath); string reason = String.Empty; diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs index fd0e879e05..2dd7767d76 100644 --- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs +++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs @@ -595,12 +595,12 @@ namespace OpenSim.Region.CoreModules.InterGrid // DEPRECATED responseMap["seed_capability"] = OSD.FromString( - regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); + regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + "/" + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); // REPLACEMENT responseMap["region_seed_capability"] = OSD.FromString( - regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); + regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + "/" + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); responseMap["rez_avatar"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); responseMap["rez_avatar/rez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs index f64a07973e..a1bcba6a37 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs @@ -124,6 +124,7 @@ namespace OpenSim.Server.Handlers.Hypergrid UUID uuid = UUID.Zero; string regionname = string.Empty; string gatekeeper_host = string.Empty; + string server_uri = string.Empty; int gatekeeper_port = 0; IPEndPoint client_ipaddress = null; @@ -173,6 +174,7 @@ namespace OpenSim.Server.Handlers.Hypergrid destination.RegionLocX = x; destination.RegionLocY = y; destination.RegionName = regionname; + AgentCircuitData aCircuit = new AgentCircuitData(); try diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 11df7e0b73..74e864b8aa 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -198,20 +198,7 @@ namespace OpenSim.Services.GridService return null; } - - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, string serverURI, out GridRegion regInfo, out string reason) - { - return TryCreateLink(scopeID, xloc, yloc, externalRegionName, 0, null, serverURI, out regInfo, out reason); - } - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) - { - return TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, out regInfo, out reason); - } - - // From the command line and the 2 above - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, - string externalRegionName, uint externalPort, string externalHostName, string serverURI, out GridRegion regInfo, out string reason) { m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0}:{1}:{2}, in {3}-{4}", externalHostName, externalPort, externalRegionName, xloc, yloc); @@ -226,8 +213,11 @@ namespace OpenSim.Services.GridService // Big HACK for Simian Grid !!! // We need to clean up all URLs used in OpenSim !!! - if (externalHostName.Contains("/")) + if (externalHostName.Contains("/")) { regInfo.ServerURI = externalHostName; + } else { + regInfo.ServerURI = "http://" + externalHostName + ":" + externalPort.ToString(); + } try { diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index d5dda115c8..aed2dc8bd2 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -136,6 +136,7 @@ namespace OpenSim.Services.HypergridService m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ExternalHostName +":"+ gatekeeper.HttpPort); + m_log.Debug("gatekeeper serveruri -> " + gatekeeper.ServerURI ); // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination GridRegion region = new GridRegion(gatekeeper); diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index bf441e6076..6d3bff7683 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -115,7 +115,13 @@ namespace OpenSim.Services.Interfaces /// public string ServerURI { - get { return m_serverURI; } + get { + if ( m_serverURI != string.Empty ) { + return m_serverURI; + } else { + return "http://" + m_externalHostName + ":" + m_httpPort + "/"; + } + } set { if ( value.EndsWith("/") ) { m_serverURI = value; @@ -170,6 +176,7 @@ namespace OpenSim.Services.Interfaces public GridRegion() { + m_serverURI = string.Empty; } public GridRegion(int regionLocX, int regionLocY, IPEndPoint internalEndPoint, string externalUri) From 94684a2251a96df0ccbc45dbb12cd241a71978f8 Mon Sep 17 00:00:00 2001 From: Jonathan Freedman Date: Wed, 20 Oct 2010 02:36:59 -0400 Subject: [PATCH 04/51] * remove some spurious debug info --- .../Servers/HttpServer/BaseHttpServer.cs | 10 +++---- .../Region/Framework/Scenes/ScenePresence.cs | 2 ++ .../Hypergrid/GatekeeperServiceConnector.cs | 30 +++++++++---------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 47e86ad56b..0c1e5e013b 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -348,7 +348,7 @@ namespace OpenSim.Framework.Servers.HttpServer { try { - m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); + //m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); @@ -376,11 +376,11 @@ namespace OpenSim.Framework.Servers.HttpServer string path = request.RawUrl; string handlerKey = GetHandlerKey(request.HttpMethod, path); - m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); + //m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); if (TryGetStreamHandler(handlerKey, out requestHandler)) { - m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); + //m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler. byte[] buffer = null; @@ -395,7 +395,7 @@ namespace OpenSim.Framework.Servers.HttpServer } else if (requestHandler is IGenericHTTPHandler) { - m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); + //m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler; Stream requestStream = request.InputStream; @@ -422,7 +422,7 @@ namespace OpenSim.Framework.Servers.HttpServer foreach (string headername in rHeaders) { - m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); + //m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); headervals[headername] = request.Headers[headername]; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 13d99643bf..c223b4b50d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2976,6 +2976,8 @@ namespace OpenSim.Region.Framework.Scenes public void CopyTo(AgentData cAgent) { + cAgent.CallbackURI = m_callbackURI; + cAgent.AgentID = UUID; cAgent.RegionID = Scene.RegionInfo.RegionID; diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 2b19b8709f..4231be1f66 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -116,19 +116,19 @@ namespace OpenSim.Services.Connectors.Hypergrid if (success) { UUID.TryParse((string)hash["uuid"], out regionID); - m_log.Debug(">> HERE, uuid: " + regionID); + //m_log.Debug(">> HERE, uuid: " + regionID); if ((string)hash["handle"] != null) { realHandle = Convert.ToUInt64((string)hash["handle"]); - m_log.Debug(">> HERE, realHandle: " + realHandle); + //m_log.Debug(">> HERE, realHandle: " + realHandle); } if (hash["region_image"] != null) { imageURL = (string)hash["region_image"]; - m_log.Debug(">> HERE, imageURL: " + imageURL); + //m_log.Debug(">> HERE, imageURL: " + imageURL); } if (hash["external_name"] != null) { externalName = (string)hash["external_name"]; - m_log.Debug(">> HERE, externalName: " + externalName); + //m_log.Debug(">> HERE, externalName: " + externalName); } } @@ -191,7 +191,7 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_region", paramList); - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); + //m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); XmlRpcResponse response = null; try { @@ -199,7 +199,7 @@ namespace OpenSim.Services.Connectors.Hypergrid } catch (Exception e) { - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message); + //m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message); return null; } @@ -210,8 +210,8 @@ namespace OpenSim.Services.Connectors.Hypergrid } hash = (Hashtable)response.Value; - foreach (Object o in hash) - m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); try { bool success = false; @@ -221,41 +221,41 @@ namespace OpenSim.Services.Connectors.Hypergrid GridRegion region = new GridRegion(); UUID.TryParse((string)hash["uuid"], out region.RegionID); - m_log.Debug(">> HERE, uuid: " + 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); + //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); + //m_log.Debug(">> HERE, y: " + region.RegionLocY); } if (hash["region_name"] != null) { region.RegionName = (string)hash["region_name"]; - m_log.Debug(">> HERE, region_name: " + region.RegionName); + //m_log.Debug(">> HERE, region_name: " + region.RegionName); } if (hash["hostname"] != null) region.ExternalHostName = (string)hash["hostname"]; - m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); + //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); if (hash["http_port"] != null) { uint p = 0; UInt32.TryParse((string)hash["http_port"], out p); region.HttpPort = p; - m_log.Debug(">> HERE, http_port: " + region.HttpPort); + //m_log.Debug(">> HERE, http_port: " + region.HttpPort); } 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); - m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); + //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); } // Successful return From 55974df14b6d64c1e1f9e386a3eacce3ba86dc98 Mon Sep 17 00:00:00 2001 From: Jonathan Freedman Date: Sat, 2 Oct 2010 19:17:02 -0400 Subject: [PATCH 05/51] * refactor refactor refactor ServerURI 4 lyfe --- OpenSim/Framework/RegionInfo.cs | 8 +++- .../Servers/HttpServer/BaseHttpServer.cs | 10 ++--- OpenSim/Region/Application/OpenSimBase.cs | 2 +- .../EntityTransfer/EntityTransferModule.cs | 27 +++-------- .../World/WorldMap/WorldMapModule.cs | 2 +- .../Hypergrid/GatekeeperServiceConnector.cs | 31 ++++++++----- .../Connectors/Land/LandServiceConnector.cs | 3 +- .../Neighbour/NeighbourServiceConnector.cs | 2 +- .../SimianGrid/SimianGridServiceConnector.cs | 4 +- .../Simulation/SimulationServiceConnector.cs | 45 +++---------------- .../Services/GridService/HypergridLinker.cs | 14 +++++- .../HypergridService/GatekeeperService.cs | 2 +- .../HypergridService/UserAgentService.cs | 8 ++-- OpenSim/Services/Interfaces/IGridService.cs | 8 +++- 14 files changed, 72 insertions(+), 94 deletions(-) diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 08d5398a18..949a28985e 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -116,7 +116,13 @@ namespace OpenSim.Framework public string ServerURI { get { return m_serverURI; } - set { m_serverURI = value; } + set { + if ( value.EndsWith("/") ) { + m_serverURI = value; + } else { + m_serverURI = value + '/'; + } + } } protected string m_serverURI; diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index ba8c1941a8..47e86ad56b 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -348,7 +348,7 @@ namespace OpenSim.Framework.Servers.HttpServer { try { -// m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); + m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); @@ -376,11 +376,11 @@ namespace OpenSim.Framework.Servers.HttpServer string path = request.RawUrl; string handlerKey = GetHandlerKey(request.HttpMethod, path); -// m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); + m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); if (TryGetStreamHandler(handlerKey, out requestHandler)) { - //m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); + m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler. byte[] buffer = null; @@ -395,7 +395,7 @@ namespace OpenSim.Framework.Servers.HttpServer } else if (requestHandler is IGenericHTTPHandler) { - //m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); + m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler; Stream requestStream = request.InputStream; @@ -422,7 +422,7 @@ namespace OpenSim.Framework.Servers.HttpServer foreach (string headername in rHeaders) { - //m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); + m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); headervals[headername] = request.Headers[headername]; } diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 74ad1685f9..f30a8504fe 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -327,8 +327,8 @@ namespace OpenSim //regionInfo.originRegionID = regionInfo.RegionID; // set initial ServerURI - regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.InternalEndPoint.Port; regionInfo.HttpPort = m_httpServerPort; + regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort.ToString(); regionInfo.osSecret = m_osSecret; diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 38fff1cab3..3791e1df6f 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -337,20 +337,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (sp.ClientView.TryGet(out ipepClient)) { capsPath - = "http://" - + NetworkUtil.GetHostFor(ipepClient.EndPoint, finalDestination.ExternalHostName) - + ":" - + finalDestination.HttpPort - + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } else { - capsPath - = "http://" - + finalDestination.ExternalHostName - + ":" - + finalDestination.HttpPort - + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } #endregion @@ -382,8 +373,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer else { agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); - capsPath = "http://" + finalDestination.ExternalHostName + ":" + finalDestination.HttpPort - + "/CAPS/" + agentCircuit.CapsPath + "0000/"; + capsPath = finalDestination.ServerURI + "/CAPS/" + agentCircuit.CapsPath + "0000/"; } // Expect avatar crossing is a heavy-duty function at the destination. @@ -516,8 +506,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) { - agent.CallbackURI = "http://" + region.ExternalHostName + ":" + region.HttpPort + - "/agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; + agent.CallbackURI = region.ServerURI + "/agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; } @@ -842,7 +831,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer cAgent.Position = pos; if (isFlying) cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; - cAgent.CallbackURI = "http://" + m_scene.RegionInfo.ExternalHostName + ":" + m_scene.RegionInfo.HttpPort + + cAgent.CallbackURI = m_scene.RegionInfo.ServerURI + "/agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) @@ -870,8 +859,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } // TODO Should construct this behind a method string capsPath = - "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort - + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/"; + neighbourRegion.ServerURI + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/"; m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); @@ -1190,8 +1178,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer y = y / Constants.RegionSize; m_log.Info("[ENTITY TRANSFER MODULE]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")"); - string capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort - + "/CAPS/" + a.CapsPath + "0000/"; + string capsPath = reg.ServerURI + "/CAPS/" + a.CapsPath + "0000/"; string reason = String.Empty; diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index a182eeae7d..3ce964af49 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -147,7 +147,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString(); regionimage = regionimage.Replace("-", ""); - m_log.Info("[WORLD MAP]: JPEG Map location: http://" + m_scene.RegionInfo.ExternalEndPoint.Address.ToString() + ":" + m_scene.RegionInfo.HttpPort.ToString() + "/index.php?method=" + regionimage); + m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "/index.php?method=" + regionimage); MainServer.Instance.AddHTTPHandler(regionimage, OnHTTPGetMapImage); MainServer.Instance.AddLLSDHandler( diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 479a80e297..89a8f7a1b8 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -108,8 +108,8 @@ namespace OpenSim.Services.Connectors.Hypergrid } hash = (Hashtable)response.Value; - //foreach (Object o in hash) - // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + foreach (Object o in hash) + m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); try { bool success = false; @@ -117,16 +117,20 @@ namespace OpenSim.Services.Connectors.Hypergrid if (success) { UUID.TryParse((string)hash["uuid"], out regionID); - //m_log.Debug(">> HERE, uuid: " + uuid); + m_log.Debug(">> HERE, uuid: " + regionID); if ((string)hash["handle"] != null) { realHandle = Convert.ToUInt64((string)hash["handle"]); - //m_log.Debug(">> HERE, realHandle: " + realHandle); + m_log.Debug(">> HERE, realHandle: " + realHandle); } - if (hash["region_image"] != null) + if (hash["region_image"] != null) { imageURL = (string)hash["region_image"]; - if (hash["external_name"] != null) + m_log.Debug(">> HERE, imageURL: " + imageURL); + } + if (hash["external_name"] != null) { externalName = (string)hash["external_name"]; + m_log.Debug(">> HERE, externalName: " + externalName); + } } } @@ -208,8 +212,8 @@ namespace OpenSim.Services.Connectors.Hypergrid } hash = (Hashtable)response.Value; - //foreach (Object o in hash) - // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + foreach (Object o in hash) + m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); try { bool success = false; @@ -219,38 +223,41 @@ namespace OpenSim.Services.Connectors.Hypergrid GridRegion region = new GridRegion(); UUID.TryParse((string)hash["uuid"], out region.RegionID); - //m_log.Debug(">> HERE, uuid: " + 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); + 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); + 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); + m_log.Debug(">> HERE, region_name: " + region.RegionName); } if (hash["hostname"] != null) region.ExternalHostName = (string)hash["hostname"]; + m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); if (hash["http_port"] != null) { uint p = 0; UInt32.TryParse((string)hash["http_port"], out p); region.HttpPort = p; + m_log.Debug(">> HERE, http_port: " + region.HttpPort); } 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); + m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); } // Successful return diff --git a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs index 8143b5a89f..4b25ac819a 100644 --- a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs +++ b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs @@ -84,8 +84,7 @@ namespace OpenSim.Services.Connectors if (info != null) // just to be sure { XmlRpcRequest request = new XmlRpcRequest("land_data", paramList); - string uri = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"; - XmlRpcResponse response = request.Send(uri, 10000); + XmlRpcResponse response = request.Send(info.ServerURI, 10000); if (response.IsFault) { m_log.ErrorFormat("[LAND CONNECTOR]: remote call returned an error: {0}", response.FaultString); diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs index 0a982f8d57..9c57a40701 100644 --- a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs +++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs @@ -87,7 +87,7 @@ namespace OpenSim.Services.Connectors public bool DoHelloNeighbourCall(GridRegion region, RegionInfo thisRegion) { - string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/region/" + thisRegion.RegionID + "/"; + string uri = region.ServerURI + "/region/" + thisRegion.RegionID + "/"; //m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri); WebRequest HelloNeighbourRequest = WebRequest.Create(uri); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index 168b233893..8076fab589 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -145,8 +145,6 @@ namespace OpenSim.Services.Connectors.SimianGrid Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0); - string httpAddress = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort + "/"; - OSDMap extraData = new OSDMap { { "ServerURI", OSD.FromString(regionInfo.ServerURI) }, @@ -168,7 +166,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Name", regionInfo.RegionName }, { "MinPosition", minPosition.ToString() }, { "MaxPosition", maxPosition.ToString() }, - { "Address", httpAddress }, + { "Address", regionInfo.ServerURI }, { "Enabled", "1" }, { "ExtraData", OSDParser.SerializeJsonString(extraData) } }; diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index a5f748f0c4..07839d3b59 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -104,24 +104,7 @@ namespace OpenSim.Services.Connectors.Simulation return false; } - string uri = string.Empty; - - // HACK -- Simian grid make it work!!! - if (destination.ServerURI != null && destination.ServerURI != string.Empty && !destination.ServerURI.StartsWith("http:")) - uri = "http://" + destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; - else - { - try - { - uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + aCircuit.AgentID + "/"; - } - catch (Exception e) - { - m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent create. Reason: " + e.Message); - reason = e.Message; - return false; - } - } + string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri); @@ -277,16 +260,7 @@ namespace OpenSim.Services.Connectors.Simulation private bool UpdateAgent(GridRegion destination, IAgentData cAgentData) { // Eventually, we want to use a caps url instead of the agentID - string uri = string.Empty; - try - { - uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + cAgentData.AgentID + "/"; - } - catch (Exception e) - { - m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent update. Reason: " + e.Message); - return false; - } + string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; //Console.WriteLine(" >>> DoAgentUpdateCall <<< " + uri); HttpWebRequest ChildUpdateRequest = (HttpWebRequest)WebRequest.Create(uri); @@ -385,7 +359,7 @@ namespace OpenSim.Services.Connectors.Simulation { agent = null; // Eventually, we want to use a caps url instead of the agentID - string uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; //Console.WriteLine(" >>> DoRetrieveRootAgentCall <<< " + uri); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); @@ -479,16 +453,7 @@ namespace OpenSim.Services.Connectors.Simulation public bool CloseAgent(GridRegion destination, UUID id) { - string uri = string.Empty; - try - { - uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; - } - catch (Exception e) - { - m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent close. Reason: " + e.Message); - return false; - } + string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri); @@ -538,7 +503,7 @@ namespace OpenSim.Services.Connectors.Simulation public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall) { string uri - = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + ObjectPath() + sog.UUID + "/"; + = destination.ServerURI + ObjectPath() + sog.UUID + "/"; //m_log.Debug(" >>> DoCreateObjectCall <<< " + uri); WebRequest ObjectCreateRequest = WebRequest.Create(uri); diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index b86fb6f01c..757ae80a70 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -127,7 +127,7 @@ namespace OpenSim.Services.GridService if (MainConsole.Instance != null) { MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region", - "link-region :[:] ", + "link-region [] ", "Link a hypergrid region", RunCommand); MainConsole.Instance.Commands.AddCommand("hypergrid", false, "unlink-region", "unlink-region or : ", @@ -200,9 +200,15 @@ namespace OpenSim.Services.GridService } - // From the command line and the 2 above public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) + { + TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, regInfo, reason); + } + + // From the command line and the 2 above + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, + string externalRegionName, uint externalPort, string externalHostName, string serverURI, out GridRegion regInfo, out string reason) { m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0}:{1}:{2}, in {3}-{4}", externalHostName, externalPort, externalRegionName, xloc, yloc); @@ -509,12 +515,16 @@ namespace OpenSim.Services.GridService int xloc, yloc; uint externalPort; string externalHostName; + string serverURI; try { xloc = Convert.ToInt32(cmdparams[0]); yloc = Convert.ToInt32(cmdparams[1]); externalPort = Convert.ToUInt32(cmdparams[3]); externalHostName = cmdparams[2]; + if ( cmdparams.Length == 4 ) { + + } //internalPort = Convert.ToUInt32(cmdparams[4]); //remotingPort = Convert.ToUInt32(cmdparams[5]); } diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs index 3f5c4f1400..9e961636ce 100644 --- a/OpenSim/Services/HypergridService/GatekeeperService.cs +++ b/OpenSim/Services/HypergridService/GatekeeperService.cs @@ -157,7 +157,7 @@ namespace OpenSim.Services.HypergridService string regionimage = "regionImage" + region.RegionID.ToString(); regionimage = regionimage.Replace("-", ""); - imageURL = "http://" + region.ExternalHostName + ":" + region.HttpPort + "/index.php?method=" + regionimage; + imageURL = region.ServerURI + "index.php?method=" + regionimage; return true; } diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index eb6433cc6f..d5dda115c8 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -145,12 +145,12 @@ namespace OpenSim.Services.HypergridService region.RegionLocY = finalDestination.RegionLocY; // Generate a new service session - agentCircuit.ServiceSessionID = "http://" + region.ExternalHostName + ":" + region.HttpPort + ";" + UUID.Random(); + agentCircuit.ServiceSessionID = region.ServerURI + ";" + UUID.Random(); TravelingAgentInfo old = UpdateTravelInfo(agentCircuit, region); bool success = false; string myExternalIP = string.Empty; - string gridName = "http://" + gatekeeper.ExternalHostName + ":" + gatekeeper.HttpPort; + string gridName = gatekeeper.ServerURI; if (m_GridName == gridName) success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); else @@ -159,7 +159,7 @@ namespace OpenSim.Services.HypergridService if (!success) { m_log.DebugFormat("[USER AGENT SERVICE]: Unable to login user {0} {1} to grid {2}, reason: {3}", - agentCircuit.firstname, agentCircuit.lastname, region.ExternalHostName + ":" + region.HttpPort, reason); + agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason); // restore the old travel info lock (m_TravelingAgents) @@ -210,7 +210,7 @@ namespace OpenSim.Services.HypergridService m_TravelingAgents[agentCircuit.SessionID] = travel; } travel.UserID = agentCircuit.AgentID; - travel.GridExternalName = "http://" + region.ExternalHostName + ":" + region.HttpPort; + travel.GridExternalName = region.ServerURI; travel.ServiceToken = agentCircuit.ServiceSessionID; if (old != null) travel.ClientIPAddress = old.ClientIPAddress; diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index 77230a33d7..bf441e6076 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -116,7 +116,13 @@ namespace OpenSim.Services.Interfaces public string ServerURI { get { return m_serverURI; } - set { m_serverURI = value; } + set { + if ( value.EndsWith("/") ) { + m_serverURI = value; + } else { + m_serverURI = value + '/'; + } + } } protected string m_serverURI; From 19119d7705f8381a3c207d0e64a23243215a12b9 Mon Sep 17 00:00:00 2001 From: Jonathan Freedman Date: Sun, 3 Oct 2010 18:03:53 -0400 Subject: [PATCH 06/51] * additional serveruri cleanup --- OpenSim/Region/Application/OpenSimBase.cs | 2 +- .../InstantMessage/MessageTransferModule.cs | 6 ++-- .../World/WorldMap/WorldMapModule.cs | 2 +- .../Hypergrid/GatekeeperServiceConnector.cs | 14 ++++----- .../Simulation/SimulationServiceConnector.cs | 10 +------ OpenSim/Services/GridService/GridService.cs | 2 +- .../Services/GridService/HypergridLinker.cs | 11 ++++--- .../LLLoginService/LLLoginResponse.cs | 29 +------------------ 8 files changed, 21 insertions(+), 55 deletions(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index f30a8504fe..904a50c799 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -328,7 +328,7 @@ namespace OpenSim // set initial ServerURI regionInfo.HttpPort = m_httpServerPort; - regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort.ToString(); + regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort.ToString() + "/"; regionInfo.osSecret = m_osSecret; diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 918fa04143..fdc48c6b69 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -599,7 +599,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage try { - XmlRpcResponse GridResp = GridReq.Send("http://" + reginfo.ExternalHostName + ":" + reginfo.HttpPort, 3000); + XmlRpcResponse GridResp = GridReq.Send(reginfo.ServerURI, 3000); Hashtable responseData = (Hashtable)GridResp.Value; @@ -621,8 +621,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } catch (WebException e) { - m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to http://{0}:{1} the host didn't respond ({2})", - reginfo.ExternalHostName, reginfo.HttpPort, e.Message); + m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0}} the host didn't respond ({2})", + reginfo.ServerURI, e.Message); } return false; diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 3ce964af49..fdbbccfbab 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -579,7 +579,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (mreg != null) { - httpserver = "http://" + mreg.ExternalEndPoint.Address.ToString() + ":" + mreg.HttpPort + "/MAP/MapItems/" + regionhandle.ToString(); + httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString(); lock (m_cachedRegionMapItemsAddress) { if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 89a8f7a1b8..2b19b8709f 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -63,12 +63,12 @@ namespace OpenSim.Services.Connectors.Hypergrid protected override string AgentPath() { - return "/foreignagent/"; + return "foreignagent/"; } protected override string ObjectPath() { - return "/foreignobject/"; + return "foreignobject/"; } public bool LinkRegion(GridRegion info, out UUID regionID, out ulong realHandle, out string externalName, out string imageURL, out string reason) @@ -86,12 +86,11 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("link_region", paramList); - string uri = "http://" + ((info.ServerURI != null && info.ServerURI != string.Empty && !info.ServerURI.StartsWith("http:")) ? info.ServerURI : info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"); - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Linking to " + uri); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Linking to " + info.ServerURI); XmlRpcResponse response = null; try { - response = request.Send(uri, 10000); + response = request.Send(info.ServerURI, 10000); } catch (Exception e) { @@ -192,12 +191,11 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_region", paramList); - string uri = "http://" + ((gatekeeper.ServerURI != null && gatekeeper.ServerURI != string.Empty && !gatekeeper.ServerURI.StartsWith("http:")) ? gatekeeper.ServerURI : gatekeeper.ExternalEndPoint.Address + ":" + gatekeeper.HttpPort + "/"); - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + uri); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); XmlRpcResponse response = null; try { - response = request.Send(uri, 10000); + response = request.Send(gatekeeper.ServerURI, 10000); } catch (Exception e) { diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 07839d3b59..c4284eb920 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -72,7 +72,7 @@ namespace OpenSim.Services.Connectors.Simulation protected virtual string AgentPath() { - return "/agent/"; + return "agent/"; } public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) @@ -106,8 +106,6 @@ namespace OpenSim.Services.Connectors.Simulation string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; - //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri); - AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri); AgentCreateRequest.Method = "POST"; AgentCreateRequest.ContentType = "application/json"; @@ -261,7 +259,6 @@ namespace OpenSim.Services.Connectors.Simulation { // Eventually, we want to use a caps url instead of the agentID string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; - //Console.WriteLine(" >>> DoAgentUpdateCall <<< " + uri); HttpWebRequest ChildUpdateRequest = (HttpWebRequest)WebRequest.Create(uri); ChildUpdateRequest.Method = "PUT"; @@ -360,7 +357,6 @@ namespace OpenSim.Services.Connectors.Simulation agent = null; // Eventually, we want to use a caps url instead of the agentID string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; - //Console.WriteLine(" >>> DoRetrieveRootAgentCall <<< " + uri); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "GET"; @@ -381,7 +377,6 @@ namespace OpenSim.Services.Connectors.Simulation sr = new StreamReader(webResponse.GetResponseStream()); reply = sr.ReadToEnd().Trim(); - //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: ChilAgentUpdate reply was " + reply); } catch (WebException ex) @@ -402,7 +397,6 @@ namespace OpenSim.Services.Connectors.Simulation OSDMap args = Util.GetOSDMap(reply); if (args == null) { - //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: Error getting OSDMap from reply"); return false; } @@ -411,7 +405,6 @@ namespace OpenSim.Services.Connectors.Simulation return true; } - //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: DoRetrieveRootAgentCall returned status " + webResponse.StatusCode); return false; } @@ -455,7 +448,6 @@ namespace OpenSim.Services.Connectors.Simulation { string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; - //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri); WebRequest request = WebRequest.Create(uri); request.Method = "DELETE"; diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index e7988d6e93..125c2be8cf 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -479,7 +479,7 @@ namespace OpenSim.Services.GridService OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); MainConsole.Instance.Output(String.Format("{0,-20} {1}\n{2,-20} {3}\n{4,-39} {5}\n\n", r.RegionName, r.RegionID, - String.Format("{0},{1}", r.posX, r.posY), "http://" + r.Data["serverIP"].ToString() + ":" + r.Data["serverPort"].ToString(), + String.Format("{0},{1}", r.posX, r.posY), r.Data["serverURI"], r.Data["owner_uuid"].ToString(), flags.ToString())); } return; diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 757ae80a70..11df7e0b73 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -199,11 +199,14 @@ namespace OpenSim.Services.GridService return null; } - - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, - string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, string serverURI, out GridRegion regInfo, out string reason) { - TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, regInfo, reason); + return TryCreateLink(scopeID, xloc, yloc, externalRegionName, 0, null, serverURI, out regInfo, out reason); + } + + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) + { + return TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, out regInfo, out reason); } // From the command line and the 2 above diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index 0da1715849..f985ab21ba 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -333,34 +333,7 @@ namespace OpenSim.Services.LLLoginService private void FillOutSeedCap(AgentCircuitData aCircuit, GridRegion destination, IPEndPoint ipepClient) { - string capsSeedPath = String.Empty; - - // Don't use the following! It Fails for logging into any region not on the same port as the http server! - // Kept here so it doesn't happen again! - // response.SeedCapability = regionInfo.ServerURI + capsSeedPath; - - #region IP Translation for NAT - if (ipepClient != null) - { - capsSeedPath - = "http://" - + NetworkUtil.GetHostFor(ipepClient.Address, destination.ExternalHostName) - + ":" - + destination.HttpPort - + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); - } - else - { - capsSeedPath - = "http://" - + destination.ExternalHostName - + ":" - + destination.HttpPort - + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); - } - #endregion - - SeedCapability = capsSeedPath; + SeedCapability = destination.ServerURI + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); } private void SetDefaultValues() From 58f75fa19d9aea18283ecdbd44559efb81781c9d Mon Sep 17 00:00:00 2001 From: Jonathan Freedman Date: Mon, 11 Oct 2010 16:53:00 -0400 Subject: [PATCH 07/51] * more url / hg cleanup --- OpenSim/Framework/Capabilities/CapsUtil.cs | 2 +- OpenSim/Framework/RegionInfo.cs | 31 +++++++++++++++-- .../EntityTransfer/EntityTransferModule.cs | 34 ++++++------------- .../InterGrid/OpenGridProtocolModule.cs | 4 +-- .../Handlers/Hypergrid/HomeAgentHandlers.cs | 2 ++ .../Services/GridService/HypergridLinker.cs | 18 +++------- .../HypergridService/UserAgentService.cs | 1 + OpenSim/Services/Interfaces/IGridService.cs | 9 ++++- 8 files changed, 56 insertions(+), 45 deletions(-) diff --git a/OpenSim/Framework/Capabilities/CapsUtil.cs b/OpenSim/Framework/Capabilities/CapsUtil.cs index 0334e4b4a2..faf2708541 100644 --- a/OpenSim/Framework/Capabilities/CapsUtil.cs +++ b/OpenSim/Framework/Capabilities/CapsUtil.cs @@ -41,7 +41,7 @@ namespace OpenSim.Framework.Capabilities /// public static string GetCapsSeedPath(string capsObjectPath) { - return "/CAPS/" + capsObjectPath + "0000/"; + return "CAPS/" + capsObjectPath + "0000/"; } /// diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 949a28985e..73b8bd0120 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -115,7 +115,13 @@ namespace OpenSim.Framework /// public string ServerURI { - get { return m_serverURI; } + get { + if ( m_serverURI != string.Empty ) { + return m_serverURI; + } else { + return "http://" + m_externalHostName + ":" + m_httpPort + "/"; + } + } set { if ( value.EndsWith("/") ) { m_serverURI = value; @@ -147,6 +153,7 @@ namespace OpenSim.Framework public SimpleRegionInfo() { + m_serverURI = string.Empty; } public SimpleRegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) @@ -156,6 +163,7 @@ namespace OpenSim.Framework m_internalEndPoint = internalEndPoint; m_externalHostName = externalUri; + m_serverURI = string.Empty; } public SimpleRegionInfo(uint regionLocX, uint regionLocY, string externalUri, uint port) @@ -166,6 +174,7 @@ namespace OpenSim.Framework m_externalHostName = externalUri; m_internalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int) port); + m_serverURI = string.Empty; } public SimpleRegionInfo(RegionInfo ConvertFrom) @@ -455,6 +464,7 @@ namespace OpenSim.Framework configMember = new ConfigurationMember(xmlNode, description, loadConfigurationOptions, handleIncomingConfiguration, !skipConsoleConfig); configMember.performConfigurationRetrieve(); + m_serverURI = string.Empty; } public RegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) @@ -464,10 +474,12 @@ namespace OpenSim.Framework m_internalEndPoint = internalEndPoint; m_externalHostName = externalUri; + m_serverURI = string.Empty; } public RegionInfo() { + m_serverURI = string.Empty; } public EstateSettings EstateSettings @@ -557,10 +569,23 @@ namespace OpenSim.Framework /// /// A well-formed URI for the host region server (namely "http://" + ExternalHostName) /// + public string ServerURI { - get { return m_serverURI; } - set { m_serverURI = value; } + get { + if ( m_serverURI != string.Empty ) { + return m_serverURI; + } else { + return "http://" + m_externalHostName + ":" + m_httpPort + "/"; + } + } + set { + if ( value.EndsWith("/") ) { + m_serverURI = value; + } else { + m_serverURI = value + '/'; + } + } } public string RegionName diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 3791e1df6f..54cc80f384 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -327,34 +327,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // OK, it got this agent. Let's close some child agents sp.CloseChildAgents(newRegionX, newRegionY); - + IClientIPEndpoint ipepClient; if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY)) { //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); - #region IP Translation for NAT - IClientIPEndpoint ipepClient; + // Uses ipepClient above if (sp.ClientView.TryGet(out ipepClient)) { - capsPath - = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); - } - else - { - capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); } #endregion + capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); 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, @@ -373,7 +360,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer else { agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); - capsPath = finalDestination.ServerURI + "/CAPS/" + agentCircuit.CapsPath + "0000/"; + capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } // Expect avatar crossing is a heavy-duty function at the destination. @@ -506,7 +493,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) { - agent.CallbackURI = region.ServerURI + "/agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; + agent.CallbackURI = region.ServerURI + "agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; + m_log.Debug("Set callback URL to " + agent.CallbackURI); } @@ -832,7 +820,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (isFlying) cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; cAgent.CallbackURI = m_scene.RegionInfo.ServerURI + - "/agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; + "agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) { @@ -857,9 +845,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer neighbourRegion.RegionHandle); return agent; } - // TODO Should construct this behind a method - string capsPath = - neighbourRegion.ServerURI + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/"; + string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); @@ -1178,7 +1164,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer y = y / Constants.RegionSize; m_log.Info("[ENTITY TRANSFER MODULE]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")"); - string capsPath = reg.ServerURI + "/CAPS/" + a.CapsPath + "0000/"; + string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath); string reason = String.Empty; diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs index fd0e879e05..2dd7767d76 100644 --- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs +++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs @@ -595,12 +595,12 @@ namespace OpenSim.Region.CoreModules.InterGrid // DEPRECATED responseMap["seed_capability"] = OSD.FromString( - regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); + regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + "/" + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); // REPLACEMENT responseMap["region_seed_capability"] = OSD.FromString( - regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); + regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + "/" + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); responseMap["rez_avatar"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); responseMap["rez_avatar/rez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs index f64a07973e..a1bcba6a37 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs @@ -124,6 +124,7 @@ namespace OpenSim.Server.Handlers.Hypergrid UUID uuid = UUID.Zero; string regionname = string.Empty; string gatekeeper_host = string.Empty; + string server_uri = string.Empty; int gatekeeper_port = 0; IPEndPoint client_ipaddress = null; @@ -173,6 +174,7 @@ namespace OpenSim.Server.Handlers.Hypergrid destination.RegionLocX = x; destination.RegionLocY = y; destination.RegionName = regionname; + AgentCircuitData aCircuit = new AgentCircuitData(); try diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 11df7e0b73..74e864b8aa 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -198,20 +198,7 @@ namespace OpenSim.Services.GridService return null; } - - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, string serverURI, out GridRegion regInfo, out string reason) - { - return TryCreateLink(scopeID, xloc, yloc, externalRegionName, 0, null, serverURI, out regInfo, out reason); - } - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) - { - return TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, out regInfo, out reason); - } - - // From the command line and the 2 above - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, - string externalRegionName, uint externalPort, string externalHostName, string serverURI, out GridRegion regInfo, out string reason) { m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0}:{1}:{2}, in {3}-{4}", externalHostName, externalPort, externalRegionName, xloc, yloc); @@ -226,8 +213,11 @@ namespace OpenSim.Services.GridService // Big HACK for Simian Grid !!! // We need to clean up all URLs used in OpenSim !!! - if (externalHostName.Contains("/")) + if (externalHostName.Contains("/")) { regInfo.ServerURI = externalHostName; + } else { + regInfo.ServerURI = "http://" + externalHostName + ":" + externalPort.ToString(); + } try { diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index d5dda115c8..aed2dc8bd2 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -136,6 +136,7 @@ namespace OpenSim.Services.HypergridService m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ExternalHostName +":"+ gatekeeper.HttpPort); + m_log.Debug("gatekeeper serveruri -> " + gatekeeper.ServerURI ); // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination GridRegion region = new GridRegion(gatekeeper); diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index bf441e6076..6d3bff7683 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -115,7 +115,13 @@ namespace OpenSim.Services.Interfaces /// public string ServerURI { - get { return m_serverURI; } + get { + if ( m_serverURI != string.Empty ) { + return m_serverURI; + } else { + return "http://" + m_externalHostName + ":" + m_httpPort + "/"; + } + } set { if ( value.EndsWith("/") ) { m_serverURI = value; @@ -170,6 +176,7 @@ namespace OpenSim.Services.Interfaces public GridRegion() { + m_serverURI = string.Empty; } public GridRegion(int regionLocX, int regionLocY, IPEndPoint internalEndPoint, string externalUri) From 017b83d0a3e3ac6a1c8bc86b9bef1ee47cba059e Mon Sep 17 00:00:00 2001 From: Jonathan Freedman Date: Wed, 20 Oct 2010 02:36:59 -0400 Subject: [PATCH 08/51] * remove some spurious debug info * The last 4 commits are a patch from otakup0pe that's supposed to make URLs better somehow in an effort to make it easier to do hypergrid (I think).. But as it seems that I'm the only one who was able to apply the patch.. and I looked it over and it doesn't look like it breaks anything via the diffs.. I'll sign off on it. Signed-off-by: Teravus Ovares (Dan Olivares) --- .../Servers/HttpServer/BaseHttpServer.cs | 10 +++---- .../Region/Framework/Scenes/ScenePresence.cs | 2 ++ .../Hypergrid/GatekeeperServiceConnector.cs | 30 +++++++++---------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 47e86ad56b..0c1e5e013b 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -348,7 +348,7 @@ namespace OpenSim.Framework.Servers.HttpServer { try { - m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); + //m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); @@ -376,11 +376,11 @@ namespace OpenSim.Framework.Servers.HttpServer string path = request.RawUrl; string handlerKey = GetHandlerKey(request.HttpMethod, path); - m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); + //m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); if (TryGetStreamHandler(handlerKey, out requestHandler)) { - m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); + //m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler. byte[] buffer = null; @@ -395,7 +395,7 @@ namespace OpenSim.Framework.Servers.HttpServer } else if (requestHandler is IGenericHTTPHandler) { - m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); + //m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler; Stream requestStream = request.InputStream; @@ -422,7 +422,7 @@ namespace OpenSim.Framework.Servers.HttpServer foreach (string headername in rHeaders) { - m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); + //m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); headervals[headername] = request.Headers[headername]; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 13d99643bf..c223b4b50d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2976,6 +2976,8 @@ namespace OpenSim.Region.Framework.Scenes public void CopyTo(AgentData cAgent) { + cAgent.CallbackURI = m_callbackURI; + cAgent.AgentID = UUID; cAgent.RegionID = Scene.RegionInfo.RegionID; diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 2b19b8709f..4231be1f66 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -116,19 +116,19 @@ namespace OpenSim.Services.Connectors.Hypergrid if (success) { UUID.TryParse((string)hash["uuid"], out regionID); - m_log.Debug(">> HERE, uuid: " + regionID); + //m_log.Debug(">> HERE, uuid: " + regionID); if ((string)hash["handle"] != null) { realHandle = Convert.ToUInt64((string)hash["handle"]); - m_log.Debug(">> HERE, realHandle: " + realHandle); + //m_log.Debug(">> HERE, realHandle: " + realHandle); } if (hash["region_image"] != null) { imageURL = (string)hash["region_image"]; - m_log.Debug(">> HERE, imageURL: " + imageURL); + //m_log.Debug(">> HERE, imageURL: " + imageURL); } if (hash["external_name"] != null) { externalName = (string)hash["external_name"]; - m_log.Debug(">> HERE, externalName: " + externalName); + //m_log.Debug(">> HERE, externalName: " + externalName); } } @@ -191,7 +191,7 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_region", paramList); - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); + //m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); XmlRpcResponse response = null; try { @@ -199,7 +199,7 @@ namespace OpenSim.Services.Connectors.Hypergrid } catch (Exception e) { - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message); + //m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message); return null; } @@ -210,8 +210,8 @@ namespace OpenSim.Services.Connectors.Hypergrid } hash = (Hashtable)response.Value; - foreach (Object o in hash) - m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); try { bool success = false; @@ -221,41 +221,41 @@ namespace OpenSim.Services.Connectors.Hypergrid GridRegion region = new GridRegion(); UUID.TryParse((string)hash["uuid"], out region.RegionID); - m_log.Debug(">> HERE, uuid: " + 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); + //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); + //m_log.Debug(">> HERE, y: " + region.RegionLocY); } if (hash["region_name"] != null) { region.RegionName = (string)hash["region_name"]; - m_log.Debug(">> HERE, region_name: " + region.RegionName); + //m_log.Debug(">> HERE, region_name: " + region.RegionName); } if (hash["hostname"] != null) region.ExternalHostName = (string)hash["hostname"]; - m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); + //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); if (hash["http_port"] != null) { uint p = 0; UInt32.TryParse((string)hash["http_port"], out p); region.HttpPort = p; - m_log.Debug(">> HERE, http_port: " + region.HttpPort); + //m_log.Debug(">> HERE, http_port: " + region.HttpPort); } 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); - m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); + //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); } // Successful return From 9038218c2d67cd796242e17c7e65adbde05c8538 Mon Sep 17 00:00:00 2001 From: dahlia Date: Wed, 20 Oct 2010 20:39:05 -0700 Subject: [PATCH 09/51] fix combining of multiple physics submeshes --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 72dce6ddcb..1257804cfa 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -349,6 +349,7 @@ namespace OpenSim.Region.Physics.Meshing OpenMetaverse.Vector3 posMax = ((OSDMap)subMeshMap["PositionDomain"])["Max"].AsVector3(); OpenMetaverse.Vector3 posMin = ((OSDMap)subMeshMap["PositionDomain"])["Min"].AsVector3(); + ushort faceIndexOffset = (ushort)coords.Count; byte[] posBytes = subMeshMap["Position"].AsBinary(); for (int i = 0; i < posBytes.Length; i += 6) @@ -368,9 +369,9 @@ namespace OpenSim.Region.Physics.Meshing byte[] triangleBytes = subMeshMap["TriangleList"].AsBinary(); for (int i = 0; i < triangleBytes.Length; i += 6) { - ushort v1 = Utils.BytesToUInt16(triangleBytes, i); - ushort v2 = Utils.BytesToUInt16(triangleBytes, i + 2); - ushort v3 = Utils.BytesToUInt16(triangleBytes, i + 4); + ushort v1 = (ushort)(Utils.BytesToUInt16(triangleBytes, i) + faceIndexOffset); + ushort v2 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 2) + faceIndexOffset); + ushort v3 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 4) + faceIndexOffset); Face f = new Face(v1, v2, v3); faces.Add(f); } From 1f7577b7351e8176e12d7e5f58f01427385958c7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 21 Oct 2010 07:19:10 +0100 Subject: [PATCH 10/51] Skip empty strings in ParseString* functions --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 8bf9482e03..cc6ded7d1d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8404,6 +8404,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api for (j = 0; j < seplen; j++) { + if (separray[j].ToString() == String.Empty) + active[j] = false; + if (active[j]) { // scan all of the markers @@ -8432,6 +8435,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) { + if (spcarray[j].ToString() == String.Empty) + active[j] = false; + if (active[j]) { // scan all of the markers From 01bc4fc9da5d708cc5a3876025b99e5d1aee034d Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 21 Oct 2010 09:30:09 +0100 Subject: [PATCH 11/51] Fix the OOB error (#5102). Sorry, my bad. --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index cc6ded7d1d..92523d4ee4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8435,7 +8435,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) { - if (spcarray[j].ToString() == String.Empty) + if (spcarray[j-seplen].ToString() == String.Empty) active[j] = false; if (active[j]) From 338e7481f97e1731af1a6470b14e78cf8301215c Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 21 Oct 2010 13:21:46 +0100 Subject: [PATCH 12/51] Remove a bit of dead code relating to ObjectCapacity --- .../OptionalModules/World/MoneyModule/SampleMoneyModule.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs index 7e1b5acb7b..b84a34d288 100644 --- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs +++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs @@ -83,7 +83,6 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule // private int m_stipend = 1000; -// private int ObjectCapacity = 45000; private int ObjectCount = 0; private int PriceEnergyUnit = 0; private int PriceGroupCreate = 0; @@ -135,7 +134,6 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule public void AddRegion(Scene scene) { - // Send ObjectCapacity to Scene.. Which sends it to the SimStatsReporter. if (m_enabled) { scene.RegisterModuleInterface(this); From bb78f1c05a2ec96e3280019446524fa749bb0897 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 21 Oct 2010 15:36:32 +0100 Subject: [PATCH 13/51] Make SImStatsReporter pick ObjectCapacity striaght out of region info --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 -- OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | 10 +++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0cfc235be2..c9ae558cd2 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -599,8 +599,6 @@ namespace OpenSim.Region.Framework.Scenes StatsReporter.OnSendStatsResult += SendSimStatsPackets; StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; - StatsReporter.SetObjectCapacity(RegionInfo.ObjectCapacity); - // Old /* m_simulatorVersion = simulatorVersion diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index fd2329409e..87dcdeea14 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -108,7 +108,7 @@ namespace OpenSim.Region.Framework.Scenes private int m_activeScripts = 0; private int m_scriptLinesPerSecond = 0; - private int objectCapacity = 45000; + private int m_objectCapacity = 45000; private Scene m_scene; @@ -124,6 +124,7 @@ namespace OpenSim.Region.Framework.Scenes m_scene = scene; ReportingRegion = scene.RegionInfo; + m_objectCapacity = scene.RegionInfo.ObjectCapacity; m_report.AutoReset = true; m_report.Interval = statsUpdatesEveryMS; m_report.Elapsed += new ElapsedEventHandler(statsHeartBeat); @@ -271,7 +272,7 @@ namespace OpenSim.Region.Framework.Scenes SimStats simStats = new SimStats( - ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)objectCapacity, rb, sb, m_scene.RegionInfo.originRegionID); + ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity, rb, sb, m_scene.RegionInfo.originRegionID); handlerSendStatResult = OnSendStatsResult; if (handlerSendStatResult != null) @@ -435,11 +436,6 @@ namespace OpenSim.Region.Framework.Scenes m_activeScripts = count; } - public void SetObjectCapacity(int objects) - { - objectCapacity = objects; - } - /// /// This is for llGetRegionFPS /// From fe99f194ade94ffcc00b4a07cd8eeac9c8c69970 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 21 Oct 2010 12:00:30 -0700 Subject: [PATCH 14/51] Deleted a verbose and unneeded log message. --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 48d5a12204..74ad485bba 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3423,7 +3423,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP avp.Sender.IsTrial = false; avp.Sender.ID = agentID; - m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); + //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); OutPacket(avp, ThrottleOutPacketType.Task); } From 529fb58b7b817ef46cfc2cdba45c3133f88cd40b Mon Sep 17 00:00:00 2001 From: AdelleF Date: Thu, 21 Oct 2010 20:16:30 +0100 Subject: [PATCH 15/51] This fixes a delay in llSetLinkPrimitiveParamsFast Signed-off-by: dahlia --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 92523d4ee4..e6092d4723 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6892,7 +6892,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) { - llSetLinkPrimitiveParams(linknumber, rules); + m_host.AddScriptLPS(1); + + List parts = GetLinkParts(linknumber); + + foreach (SceneObjectPart part in parts) + SetPrimParams(part, rules); } protected void SetPrimParams(SceneObjectPart part, LSL_List rules) From 62a09103552cc87083f9107324dc4d6e4256b3d3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 21 Oct 2010 22:04:31 +0100 Subject: [PATCH 16/51] Allow region modules to know which agents actually receive chat --- .../CoreModules/Avatar/Chat/ChatModule.cs | 44 +++++++++++++++---- .../Region/Framework/Scenes/EventManager.cs | 35 +++++++++++++++ 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index ef5efdd9e5..d76ff47f87 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -167,7 +167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat // sanity check: if (c.Sender == null) { - m_log.ErrorFormat("[CHAT] OnChatFromClient from {0} has empty Sender field!", sender); + m_log.ErrorFormat("[CHAT]: OnChatFromClient from {0} has empty Sender field!", sender); return; } @@ -220,17 +220,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat if (message.Length >= 1000) // libomv limit message = message.Substring(0, 1000); - // m_log.DebugFormat("[CHAT]: DCTA: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, c.Type, sourceType); +// m_log.DebugFormat( +// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}", +// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType); + HashSet receiverIDs = new HashSet(); + foreach (Scene s in m_scenes) { s.ForEachScenePresence( delegate(ScenePresence presence) { - TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType); + if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType)) + receiverIDs.Add(presence.UUID); } ); } + + (scene as Scene).EventManager.TriggerOnChatToClients( + fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); } static private Vector3 CenterOfRegion = new Vector3(128, 128, 30); @@ -269,6 +277,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); + HashSet receiverIDs = new HashSet(); + ((Scene)c.Scene).ForEachScenePresence( delegate(ScenePresence presence) { @@ -286,16 +296,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, (byte)sourceType, (byte)ChatAudibleLevel.Fully); + receiverIDs.Add(presence.UUID); }); + + (c.Scene as Scene).EventManager.TriggerOnChatToClients( + fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); } - - protected virtual void TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, + /// + /// Try to send a message to the given presence + /// + /// The receiver + /// + /// /param> + /// + /// + /// + /// + /// + /// true if the message was sent to the receiver, false if it was not sent due to failing a + /// precondition + protected virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, UUID fromAgentID, string fromName, ChatTypeEnum type, string message, ChatSourceType src) { // don't send stuff to child agents - if (presence.IsChildAgent) return; + if (presence.IsChildAgent) return false; Vector3 fromRegionPos = fromPos + regionPos; Vector3 toRegionPos = presence.AbsolutePosition + @@ -308,12 +334,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat type == ChatTypeEnum.Say && dis > m_saydistance || type == ChatTypeEnum.Shout && dis > m_shoutdistance) { - return; + return false; } // TODO: should change so the message is sent through the avatar rather than direct to the ClientView presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, - fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully); + fromAgentID, (byte)src, (byte)ChatAudibleLevel.Fully); + + return true; } } } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 437b91a71b..4feb3fc3de 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -292,6 +292,17 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ChatFromClientEvent(Object sender, OSChatMessage chat); public event ChatFromClientEvent OnChatFromClient; + /// + /// ChatToClientsEvent is triggered via ChatModule (or + /// substitutes thereof) when a chat message is actually sent to clients. Clients will only be sent a + /// received chat message if they satisfy various conditions (within audible range, etc.) + /// + public delegate void ChatToClientsEvent( + UUID senderID, HashSet receiverIDs, + string message, ChatTypeEnum type, Vector3 fromPos, string fromName, + ChatSourceType src, ChatAudibleLevel level); + public event ChatToClientsEvent OnChatToClients; + /// /// ChatBroadcastEvent is called via Scene when a broadcast chat message /// from world comes in @@ -1603,6 +1614,30 @@ namespace OpenSim.Region.Framework.Scenes } } } + + public void TriggerOnChatToClients( + UUID senderID, HashSet receiverIDs, + string message, ChatTypeEnum type, Vector3 fromPos, string fromName, + ChatSourceType src, ChatAudibleLevel level) + { + ChatToClientsEvent handler = OnChatToClients; + if (handler != null) + { + foreach (ChatToClientsEvent d in handler.GetInvocationList()) + { + try + { + d(senderID, receiverIDs, message, type, fromPos, fromName, src, level); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[EVENT MANAGER]: Delegate for TriggerOnChatToClients failed - continuing. {0} {1}", + e.Message, e.StackTrace); + } + } + } + } public void TriggerOnChatBroadcast(Object sender, OSChatMessage chat) { From e7f184345e35931ac1dbfcfab9a3788bd4ebb11a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 01:52:19 +0100 Subject: [PATCH 17/51] minor: add some text to the oar abort messages on assets timeout to make it clear that the oar will not be usable --- OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index a1451ce705..d4a09b45f7 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -188,7 +188,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.ErrorFormat( "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT); - m_log.Error("[ARCHIVER]: OAR save aborted."); + m_log.Error("[ARCHIVER]: OAR save aborted. PLEASE DO NOT USE THIS OAR, IT WILL BE INCOMPLETE."); } catch (Exception e) { From d4144bedb81346301162f1e20266561fea7b621e Mon Sep 17 00:00:00 2001 From: Jonathan Freedman Date: Thu, 21 Oct 2010 23:22:15 -0400 Subject: [PATCH 18/51] * change the data exchanged within hypergrid transactions --- .../ClientStack/LindenUDP/LLUDPServer.cs | 2 +- .../EntityTransfer/EntityTransferModule.cs | 8 +- .../EntityTransfer/HGEntityTransferModule.cs | 5 +- OpenSim/Region/Framework/Scenes/Scene.cs | 5 +- .../Region/Framework/Scenes/ScenePresence.cs | 2 +- .../Handlers/Hypergrid/HomeAgentHandlers.cs | 10 ++- .../Hypergrid/GatekeeperServiceConnector.cs | 35 +++++---- .../Hypergrid/UserAgentServiceConnector.cs | 2 + .../Services/GridService/HypergridLinker.cs | 73 ++++++++++++++----- .../HypergridService/UserAgentService.cs | 10 ++- 10 files changed, 108 insertions(+), 44 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index cb298fdad0..624814a746 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -631,7 +631,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP IClientAPI client; if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView)) { - //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); + m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); return; } diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 54cc80f384..925af3f579 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -197,8 +197,8 @@ 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 / Constants.RegionSize, finalDestination.RegionLocY / Constants.RegionSize, finalDestination.RegionID); + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is x={0} y={1} {2}@{3}", + finalDestination.RegionLocX / Constants.RegionSize, finalDestination.RegionLocY / Constants.RegionSize, finalDestination.RegionID, finalDestination.ServerURI); // Check that these are not the same coordinates if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX && @@ -254,8 +254,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: Request Teleport to {0}:{1}:{2}/{3}", - reg.ExternalHostName, reg.HttpPort, finalDestination.RegionName, position); + "[ENTITY TRANSFER MODULE]: Request Teleport to {0} ({1}) {2}/{3}", + reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); uint newRegionX = (uint)(reg.RegionHandle >> 40); uint newRegionY = (((uint)(reg.RegionHandle)) >> 8); diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 1ac7508c20..9a275ae215 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -123,7 +123,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) { m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); - return m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); + GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); + m_log.Debug("GetfinalDestination serveruri -> " + real_destination.ServerURI); + return real_destination; } return region; } @@ -149,6 +151,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) { + m_log.Debug("CreateAgent " + reg.ServerURI + " " + finalDestination.ServerURI); reason = string.Empty; logout = false; int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, reg.RegionID); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0cfc235be2..275016892c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3740,9 +3740,12 @@ namespace OpenSim.Region.Framework.Scenes // We have to wait until the viewer contacts this region after receiving EAC. // That calls AddNewClient, which finally creates the ScenePresence + m_log.Debug("ICADU -> pre wait"); ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); + m_log.Debug("ICADU -> post wait"); if (childAgentUpdate != null) { + m_log.Debug("ICADU -> not child agent!"); childAgentUpdate.ChildAgentDataUpdate(cAgentData); return true; } @@ -3758,7 +3761,7 @@ namespace OpenSim.Region.Framework.Scenes /// true if we handled it. public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) { - //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); + m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); if (childAgentUpdate != null) { diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index c223b4b50d..68ac178e50 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2925,7 +2925,7 @@ namespace OpenSim.Region.Framework.Scenes public void ChildAgentDataUpdate(AgentData cAgentData) { - //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); + m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); if (!IsChildAgent) return; diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs index a1bcba6a37..a5ec4f2b08 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs @@ -124,7 +124,8 @@ namespace OpenSim.Server.Handlers.Hypergrid UUID uuid = UUID.Zero; string regionname = string.Empty; string gatekeeper_host = string.Empty; - string server_uri = string.Empty; + string gatekeeper_serveruri = string.Empty; + string destination_serveruri = string.Empty; int gatekeeper_port = 0; IPEndPoint client_ipaddress = null; @@ -132,8 +133,13 @@ namespace OpenSim.Server.Handlers.Hypergrid gatekeeper_host = args["gatekeeper_host"].AsString(); if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null) Int32.TryParse(args["gatekeeper_port"].AsString(), out gatekeeper_port); + if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] !=null) + gatekeeper_serveruri = args["gatekeeper_serveruri"]; + if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] !=null) + destination_serveruri = args["destination_serveruri"]; GridRegion gatekeeper = new GridRegion(); + gatekeeper.ServerURI = gatekeeper_serveruri; gatekeeper.ExternalHostName = gatekeeper_host; gatekeeper.HttpPort = (uint)gatekeeper_port; gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); @@ -174,8 +180,8 @@ namespace OpenSim.Server.Handlers.Hypergrid destination.RegionLocX = x; destination.RegionLocY = y; destination.RegionName = regionname; + destination.ServerURI = destination_serveruri; - AgentCircuitData aCircuit = new AgentCircuitData(); try { diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 4231be1f66..70bafda233 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -116,19 +116,19 @@ namespace OpenSim.Services.Connectors.Hypergrid if (success) { UUID.TryParse((string)hash["uuid"], out regionID); - //m_log.Debug(">> HERE, uuid: " + regionID); + m_log.Debug(">> HERE, uuid: " + regionID); if ((string)hash["handle"] != null) { realHandle = Convert.ToUInt64((string)hash["handle"]); - //m_log.Debug(">> HERE, realHandle: " + realHandle); + m_log.Debug(">> HERE, realHandle: " + realHandle); } if (hash["region_image"] != null) { imageURL = (string)hash["region_image"]; - //m_log.Debug(">> HERE, imageURL: " + imageURL); + m_log.Debug(">> HERE, imageURL: " + imageURL); } if (hash["external_name"] != null) { externalName = (string)hash["external_name"]; - //m_log.Debug(">> HERE, externalName: " + externalName); + m_log.Debug(">> HERE, externalName: " + externalName); } } @@ -191,7 +191,7 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_region", paramList); - //m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); XmlRpcResponse response = null; try { @@ -199,7 +199,7 @@ namespace OpenSim.Services.Connectors.Hypergrid } catch (Exception e) { - //m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message); return null; } @@ -221,41 +221,48 @@ namespace OpenSim.Services.Connectors.Hypergrid GridRegion region = new GridRegion(); UUID.TryParse((string)hash["uuid"], out region.RegionID); - //m_log.Debug(">> HERE, uuid: " + 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); + 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); + m_log.Debug(">> HERE, y: " + region.RegionLocY); } if (hash["region_name"] != null) { region.RegionName = (string)hash["region_name"]; - //m_log.Debug(">> HERE, region_name: " + region.RegionName); + m_log.Debug(">> HERE, region_name: " + region.RegionName); } - if (hash["hostname"] != null) + if (hash["hostname"] != null) { region.ExternalHostName = (string)hash["hostname"]; - //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); + m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); + } if (hash["http_port"] != null) { uint p = 0; UInt32.TryParse((string)hash["http_port"], out p); region.HttpPort = p; - //m_log.Debug(">> HERE, http_port: " + region.HttpPort); + m_log.Debug(">> HERE, http_port: " + region.HttpPort); } 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); - //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); + m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); + } + + if (hash["server_uri"] != null) + { + region.ServerURI = (string) hash["server_uri"]; + m_log.Debug(">> HERE, server_uri: " + region.ServerURI); } // Successful return diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 247dd7ed10..0c41935215 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -232,12 +232,14 @@ namespace OpenSim.Services.Connectors.Hypergrid m_log.Debug("[USER AGENT CONNECTOR]: PackAgentCircuitData failed with exception: " + e.Message); } // Add the input arguments + args["gatekeeper_serveruri"] = OSD.FromString(gatekeeper.ServerURI); args["gatekeeper_host"] = OSD.FromString(gatekeeper.ExternalHostName); args["gatekeeper_port"] = OSD.FromString(gatekeeper.HttpPort.ToString()); args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); args["destination_name"] = OSD.FromString(destination.RegionName); args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); + args["destination_serveruri"] = OSD.FromString(destination.ServerURI); // 10/3/2010 // I added the client_ip up to the regular AgentCircuitData, so this doesn't need to be here. diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 74e864b8aa..c273d21229 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -126,11 +126,12 @@ namespace OpenSim.Services.GridService if (MainConsole.Instance != null) { - MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region", - "link-region [] ", - "Link a hypergrid region", RunCommand); + MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region", "link-region []", "Link a HyperGrid Region", RunCommand); + MainConsole.Instance.Commands.AddCommand("hypergrid", false, "legacy-link-region", + "legacy-link-region []", + "Link a hypergrid region (deprecated)", RunCommand); MainConsole.Instance.Commands.AddCommand("hypergrid", false, "unlink-region", - "unlink-region or : ", + "unlink-region ", "Unlink a hypergrid region", RunCommand); MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-mapping", "link-mapping [ ] ", "Set local coordinate to map HG regions to", RunCommand); @@ -198,27 +199,33 @@ namespace OpenSim.Services.GridService return null; } + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) + { + return TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, out regInfo, out reason); + } + + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, string serverURI, out GridRegion regInfo, out string reason) { m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0}:{1}:{2}, in {3}-{4}", externalHostName, externalPort, externalRegionName, xloc, yloc); reason = string.Empty; regInfo = new GridRegion(); - regInfo.RegionName = externalRegionName; - regInfo.HttpPort = externalPort; - regInfo.ExternalHostName = externalHostName; + if ( externalPort > 0) + regInfo.HttpPort = externalPort; + else + regInfo.HttpPort = 0; + if ( externalHostName != null) + regInfo.ExternalHostName = externalHostName; + else + regInfo.ExternalHostName = "0.0.0.0"; + if ( serverURI != null) + regInfo.ServerURI = serverURI; + regInfo.RegionLocX = xloc; regInfo.RegionLocY = yloc; regInfo.ScopeID = scopeID; - // Big HACK for Simian Grid !!! - // We need to clean up all URLs used in OpenSim !!! - if (externalHostName.Contains("/")) { - regInfo.ServerURI = externalHostName; - } else { - regInfo.ServerURI = "http://" + externalHostName + ":" + externalPort.ToString(); - } - try { regInfo.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int)0); @@ -249,9 +256,14 @@ namespace OpenSim.Services.GridService } regInfo.RegionID = regionID; - if (regInfo.RegionName == string.Empty) - regInfo.RegionName = regInfo.ExternalHostName; + if ( externalName == string.Empty ) + regInfo.RegionName = regInfo.ServerURI; + else + regInfo.RegionName = externalName; + + m_log.Debug("naming linked region " + regInfo.RegionName); + // Try get the map image //regInfo.TerrainImage = m_GatekeeperConnector.GetMapImage(regionID, imageURL); // I need a texture that works for this... the one I tried doesn't seem to be working @@ -433,6 +445,21 @@ namespace OpenSim.Services.GridService RunHGCommand(command, cmdparams); } + + private void RunLinkRegionCommand(string[] cmdparams) + { + int xloc, yloc; + string serverURI; + string remoteName = null; + xloc = Convert.ToInt32(cmdparams[0]) * (int)Constants.RegionSize; + yloc = Convert.ToInt32(cmdparams[1]) * (int)Constants.RegionSize; + serverURI = cmdparams[2]; + if (cmdparams.Length == 4) + remoteName = cmdparams[3]; + string reason = string.Empty; + GridRegion regInfo; + TryCreateLink(UUID.Zero, xloc, yloc, remoteName, 0, null, serverURI, out regInfo, out reason); + } private void RunHGCommand(string command, string[] cmdparams) { @@ -455,6 +482,18 @@ namespace OpenSim.Services.GridService } } else if (command.Equals("link-region")) + { + if (cmdparams.Length > 0 && cmdparams.Length < 5) + { + RunLinkRegionCommand(cmdparams); + } + else + { + LinkRegionCmdUsage(); + } + return; + } + else if (command.Equals("legacy-link-region")) { if (cmdparams.Length < 3) { diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index aed2dc8bd2..eb19fe2fdc 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -134,12 +134,14 @@ namespace OpenSim.Services.HypergridService public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason) { m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", - agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), - gatekeeper.ExternalHostName +":"+ gatekeeper.HttpPort); - m_log.Debug("gatekeeper serveruri -> " + gatekeeper.ServerURI ); + agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); + m_log.Debug("LATG final server uri -> " + finalDestination.ServerURI ); // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination GridRegion region = new GridRegion(gatekeeper); + region.ServerURI = gatekeeper.ServerURI; + region.ExternalHostName = finalDestination.ExternalHostName; + region.InternalEndPoint = finalDestination.InternalEndPoint; region.RegionName = finalDestination.RegionName; region.RegionID = finalDestination.RegionID; region.RegionLocX = finalDestination.RegionLocX; @@ -149,6 +151,8 @@ namespace OpenSim.Services.HypergridService agentCircuit.ServiceSessionID = region.ServerURI + ";" + UUID.Random(); TravelingAgentInfo old = UpdateTravelInfo(agentCircuit, region); + m_log.Debug("region ServerURI -> " + region.ServerURI); + bool success = false; string myExternalIP = string.Empty; string gridName = gatekeeper.ServerURI; From bb28726a8bb14aaba075d6e61317dc7be624ab15 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 18:39:40 +0100 Subject: [PATCH 19/51] write IAR control file first in the archive rather than last --- .../Inventory/Archiver/InventoryArchiveWriteRequest.cs | 10 ++++++---- .../World/Archiver/ArchiveWriteRequestPreparation.cs | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index bae5a7a289..f385a2a2a8 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -123,9 +123,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver try { - // We're almost done. Just need to write out the control file now - m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p1ControlFile()); - m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); m_archiveWriter.Close(); } catch (Exception e) @@ -216,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver public void Execute() { try - { + { InventoryFolderBase inventoryFolder = null; InventoryItemBase inventoryItem = null; InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); @@ -277,6 +274,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_archiveWriter = new TarArchiveWriter(m_saveStream); + // Write out control file. This has to be done first so that subsequent loaders will see this file first + // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this + m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p1ControlFile()); + m_log.InfoFormat("[INVENTORY ARCHIVER]: Added control file to archive."); + if (inventoryFolder != null) { m_log.DebugFormat( diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 43789af9ec..1687d06350 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -171,7 +171,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); - // Write out control file + // Write out control file. This has to be done first so that subsequent loaders will see this file first + // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p2ControlFile(options)); m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); From a5bb7b8a300a9dd0aceb3666423f2827a69e1930 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 18:47:38 +0100 Subject: [PATCH 20/51] slightly simplify oar control file loading code --- .../World/Archiver/ArchiveReadRequest.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index f1f5258d1d..9192f43969 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -483,15 +483,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// private void LoadControlFile(string path, byte[] data) { - //Create the XmlNamespaceManager. - NameTable nt = new NameTable(); - XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt); - - // Create the XmlParserContext. + XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); - - XmlTextReader xtr - = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); + XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; @@ -530,10 +524,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString(); } } - } currentRegionSettings.Save(); } } -} +} \ No newline at end of file From 199b61f1b2c48c82c5878032acfa9b69e4898fec Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 19:24:42 +0100 Subject: [PATCH 21/51] start parsing iar control file This change requires a prebuild[.sh|.bat] since a System.Xml.Linq reference is added to prebuild.xml --- .../Archiver/InventoryArchiveReadRequest.cs | 20 ++++++++++++++++++- .../World/Archiver/ArchiveReadRequest.cs | 2 +- prebuild.xml | 1 + 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index c1df827069..2beea8ef6f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -33,6 +33,7 @@ using System.Reflection; using System.Threading; using System.Text; using System.Xml; +using System.Xml.Linq; using log4net; using OpenMetaverse; using OpenSim.Framework; @@ -133,7 +134,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver while ((data = archive.ReadEntry(out filePath, out entryType)) != null) { - if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + if (filePath == ArchiveConstants.CONTROL_FILE_PATH) + { + LoadControlFile(filePath, data); + } + else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) { if (LoadAsset(filePath, data)) successfulAssetRestores++; @@ -461,5 +466,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } } + + /// + /// Load control file + /// + /// + /// + protected void LoadControlFile(string path, byte[] data) + { + XDocument doc = XDocument.Parse(Encoding.ASCII.GetString(data)); + XElement archiveElement = doc.Element("archive"); + int.Parse(archiveElement.Attribute("major_version").Value); + int.Parse(archiveElement.Attribute("minor_version").Value); + } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 9192f43969..087d3dfed0 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -481,7 +481,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// /// - private void LoadControlFile(string path, byte[] data) + protected void LoadControlFile(string path, byte[] data) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); diff --git a/prebuild.xml b/prebuild.xml index b28d22697f..dd4a5769e7 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1387,6 +1387,7 @@ + From 7f2d8449169481f1ec6ee5373bdfeef83c3434bc Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 19:30:15 +0100 Subject: [PATCH 22/51] Implement guard against trying to load incompatible version IARs --- .../Archiver/InventoryArchiveReadRequest.cs | 21 +++++++++++++++++-- .../World/Archiver/ArchiveReadRequest.cs | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 2beea8ef6f..55005572ba 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -51,6 +51,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// + /// The maximum major version of archive that we can read. Minor versions shouldn't need a max number since version + /// bumps here should be compatible. + /// + public static int MAX_MAJOR_VERSION = 0; + protected TarArchiveReader archive; private UserAccount m_userInfo; @@ -476,8 +482,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { XDocument doc = XDocument.Parse(Encoding.ASCII.GetString(data)); XElement archiveElement = doc.Element("archive"); - int.Parse(archiveElement.Attribute("major_version").Value); - int.Parse(archiveElement.Attribute("minor_version").Value); + int majorVersion = int.Parse(archiveElement.Attribute("major_version").Value); + int minorVersion = int.Parse(archiveElement.Attribute("minor_version").Value); + string version = string.Format("{0}.{1}", majorVersion, minorVersion); + + if (majorVersion > MAX_MAJOR_VERSION) + { + throw new Exception( + string.Format( + "The IAR you are trying to load has major version number of {0} but this version of OpenSim can only load IARs with major version number {1} and below", + majorVersion, MAX_MAJOR_VERSION)); + } + + m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 087d3dfed0..117b2fd2fc 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// - /// The maximum major version of OAR that we can read. Minor versions shouldn't need a number since version + /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version /// bumps here should be compatible. /// public static int MAX_MAJOR_VERSION = 0; From e6019dd6ac16ea3947e127be510bc3084b4bf103 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 19:34:06 +0100 Subject: [PATCH 23/51] print IAR version number on console when saving --- .../Inventory/Archiver/InventoryArchiveWriteRequest.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index f385a2a2a8..249a8b4b9c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -401,13 +401,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// public static string Create0p1ControlFile() { + int majorVersion = 0, minorVersion = 1; + + m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); + StringWriter sw = new StringWriter(); XmlTextWriter xtw = new XmlTextWriter(sw); xtw.Formatting = Formatting.Indented; xtw.WriteStartDocument(); xtw.WriteStartElement("archive"); - xtw.WriteAttributeString("major_version", "0"); - xtw.WriteAttributeString("minor_version", "1"); + xtw.WriteAttributeString("major_version", majorVersion.ToString()); + xtw.WriteAttributeString("minor_version", minorVersion.ToString()); xtw.WriteEndElement(); xtw.Flush(); From 1064e743beb3095dcfcfc22ae341f7efba48b648 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 21:12:22 +0100 Subject: [PATCH 24/51] Allow OARs and IARs to save and load meshes. Save and reload appears okay for the duck mesh at https://collada.org/owl/download.php?sess=0&parent=126&expand=1&order=name&curview=0&binary=1&id=698/ However, one attempt at trying to load a more complicated scene failed (errors on console, only triangles appearing in mesh viewer). Not sure if this is really and OAR load problem. Needs more investigation. --- OpenSim/Framework/Serialization/ArchiveConstants.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs index 7a9b33dc8c..2c5e0018ec 100644 --- a/OpenSim/Framework/Serialization/ArchiveConstants.cs +++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs @@ -112,6 +112,7 @@ namespace OpenSim.Framework.Serialization ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LostAndFoundFolder] = ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"; // Not sure if we'll ever see this ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLBytecode] = ASSET_EXTENSION_SEPARATOR + "bytecode.lso"; ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLText] = ASSET_EXTENSION_SEPARATOR + "script.lsl"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Mesh] = ASSET_EXTENSION_SEPARATOR + "mesh.llmesh"; ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Notecard] = ASSET_EXTENSION_SEPARATOR + "notecard.txt"; ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Object] = ASSET_EXTENSION_SEPARATOR + "object.xml"; ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.RootFolder] = ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"; // Not sure if we'll ever see this @@ -135,6 +136,7 @@ namespace OpenSim.Framework.Serialization EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"] = (sbyte)AssetType.LostAndFoundFolder; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bytecode.lso"] = (sbyte)AssetType.LSLBytecode; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "script.lsl"] = (sbyte)AssetType.LSLText; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "mesh.llmesh"] = (sbyte)AssetType.Mesh; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "notecard.txt"] = (sbyte)AssetType.Notecard; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "object.xml"] = (sbyte)AssetType.Object; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"] = (sbyte)AssetType.RootFolder; From cfbaad36691667e08b4b155abf8c8c2cc310dc12 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 21:28:10 +0100 Subject: [PATCH 25/51] Fix llParcelMediaCommandList() so that it applies commands only to the parcel that the script is in, not all parcels. Patch from http://opensimulator.org/mantis/view.php?id=2738 Thanks snoopy and fineman. --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e6092d4723..59a36187cf 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9101,10 +9101,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // do that one last, it will cause a ParcelPropertiesUpdate landObject.SetMediaUrl(url); - // now send to all (non-child) agents + // now send to all (non-child) agents in the parcel World.ForEachScenePresence(delegate(ScenePresence sp) { - if (!sp.IsChildAgent) + if (!sp.IsChildAgent && (sp.currentParcelUUID == landData.GlobalID)) { sp.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, landData.MediaID, @@ -9134,10 +9134,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // the commandList contained a start/stop/... command, too if (presence == null) { - // send to all (non-child) agents + // send to all (non-child) agents in the parcel World.ForEachScenePresence(delegate(ScenePresence sp) { - if (!sp.IsChildAgent) + if (!sp.IsChildAgent && (sp.currentParcelUUID == landData.GlobalID)) { sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? (ParcelMediaCommandEnum)commandToSend, From 700f4ddea49a416f5ec7a6a4f26454be93d5da91 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 22 Oct 2010 13:29:59 +0100 Subject: [PATCH 26/51] Change some exception to use ToString(). e.Message is not sufficient to fix errors. Please don't use e.Message, devs NEED to see the dumps! --- OpenSim/Region/Framework/Scenes/Scene.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ef18d02323..4878b3e46d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2395,7 +2395,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.WarnFormat("[SCENE]: Problem casting object: {0}", e.Message); + m_log.WarnFormat("[SCENE]: Problem casting object: " + e.ToString()); return false; } @@ -3347,7 +3347,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.DebugFormat("[CONNECTION BEGIN]: Exception verifying presence {0}", e.Message); + m_log.ErrorFormat("[CONNECTION BEGIN]: Exception verifying presence " + e.ToString()); return false; } @@ -3358,7 +3358,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.DebugFormat("[CONNECTION BEGIN]: Exception authorizing user {0}", e.Message); + m_log.ErrorFormat("[CONNECTION BEGIN]: Exception authorizing user " + e.ToString()); return false; } From 6049e548a5eb33adc41141c365acffd73642b600 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 21 Oct 2010 07:19:10 +0100 Subject: [PATCH 27/51] Skip empty strings in ParseString* functions --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 8bf9482e03..cc6ded7d1d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8404,6 +8404,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api for (j = 0; j < seplen; j++) { + if (separray[j].ToString() == String.Empty) + active[j] = false; + if (active[j]) { // scan all of the markers @@ -8432,6 +8435,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) { + if (spcarray[j].ToString() == String.Empty) + active[j] = false; + if (active[j]) { // scan all of the markers From 753137e9ad1c26fa948c51644dc9c1e80ecc0d5f Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 21 Oct 2010 09:30:09 +0100 Subject: [PATCH 28/51] Fix the OOB error (#5102). Sorry, my bad. --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index cc6ded7d1d..92523d4ee4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8435,7 +8435,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) { - if (spcarray[j].ToString() == String.Empty) + if (spcarray[j-seplen].ToString() == String.Empty) active[j] = false; if (active[j]) From 170c5d183bdfc6c9b8029ef70deede48bf99cfeb Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 21 Oct 2010 13:21:46 +0100 Subject: [PATCH 29/51] Remove a bit of dead code relating to ObjectCapacity --- .../OptionalModules/World/MoneyModule/SampleMoneyModule.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs index 7e1b5acb7b..b84a34d288 100644 --- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs +++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs @@ -83,7 +83,6 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule // private int m_stipend = 1000; -// private int ObjectCapacity = 45000; private int ObjectCount = 0; private int PriceEnergyUnit = 0; private int PriceGroupCreate = 0; @@ -135,7 +134,6 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule public void AddRegion(Scene scene) { - // Send ObjectCapacity to Scene.. Which sends it to the SimStatsReporter. if (m_enabled) { scene.RegisterModuleInterface(this); From 004b395d12b4e369005a4f4a0a44a86bd278e781 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 21 Oct 2010 15:36:32 +0100 Subject: [PATCH 30/51] Make SImStatsReporter pick ObjectCapacity striaght out of region info --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 -- OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | 10 +++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0cfc235be2..c9ae558cd2 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -599,8 +599,6 @@ namespace OpenSim.Region.Framework.Scenes StatsReporter.OnSendStatsResult += SendSimStatsPackets; StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; - StatsReporter.SetObjectCapacity(RegionInfo.ObjectCapacity); - // Old /* m_simulatorVersion = simulatorVersion diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index fd2329409e..87dcdeea14 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -108,7 +108,7 @@ namespace OpenSim.Region.Framework.Scenes private int m_activeScripts = 0; private int m_scriptLinesPerSecond = 0; - private int objectCapacity = 45000; + private int m_objectCapacity = 45000; private Scene m_scene; @@ -124,6 +124,7 @@ namespace OpenSim.Region.Framework.Scenes m_scene = scene; ReportingRegion = scene.RegionInfo; + m_objectCapacity = scene.RegionInfo.ObjectCapacity; m_report.AutoReset = true; m_report.Interval = statsUpdatesEveryMS; m_report.Elapsed += new ElapsedEventHandler(statsHeartBeat); @@ -271,7 +272,7 @@ namespace OpenSim.Region.Framework.Scenes SimStats simStats = new SimStats( - ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)objectCapacity, rb, sb, m_scene.RegionInfo.originRegionID); + ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity, rb, sb, m_scene.RegionInfo.originRegionID); handlerSendStatResult = OnSendStatsResult; if (handlerSendStatResult != null) @@ -435,11 +436,6 @@ namespace OpenSim.Region.Framework.Scenes m_activeScripts = count; } - public void SetObjectCapacity(int objects) - { - objectCapacity = objects; - } - /// /// This is for llGetRegionFPS /// From 481a44104edd2ec24b92a97dbc1766be2fb1dc70 Mon Sep 17 00:00:00 2001 From: AdelleF Date: Thu, 21 Oct 2010 20:16:30 +0100 Subject: [PATCH 31/51] This fixes a delay in llSetLinkPrimitiveParamsFast Signed-off-by: dahlia --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 92523d4ee4..e6092d4723 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6892,7 +6892,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) { - llSetLinkPrimitiveParams(linknumber, rules); + m_host.AddScriptLPS(1); + + List parts = GetLinkParts(linknumber); + + foreach (SceneObjectPart part in parts) + SetPrimParams(part, rules); } protected void SetPrimParams(SceneObjectPart part, LSL_List rules) From e06acae965d918ac0ece14a8aae2e1cf5be37d07 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 21 Oct 2010 22:04:31 +0100 Subject: [PATCH 32/51] Allow region modules to know which agents actually receive chat --- .../CoreModules/Avatar/Chat/ChatModule.cs | 44 +++++++++++++++---- .../Region/Framework/Scenes/EventManager.cs | 35 +++++++++++++++ 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index ef5efdd9e5..d76ff47f87 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -167,7 +167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat // sanity check: if (c.Sender == null) { - m_log.ErrorFormat("[CHAT] OnChatFromClient from {0} has empty Sender field!", sender); + m_log.ErrorFormat("[CHAT]: OnChatFromClient from {0} has empty Sender field!", sender); return; } @@ -220,17 +220,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat if (message.Length >= 1000) // libomv limit message = message.Substring(0, 1000); - // m_log.DebugFormat("[CHAT]: DCTA: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, c.Type, sourceType); +// m_log.DebugFormat( +// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}", +// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType); + HashSet receiverIDs = new HashSet(); + foreach (Scene s in m_scenes) { s.ForEachScenePresence( delegate(ScenePresence presence) { - TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType); + if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType)) + receiverIDs.Add(presence.UUID); } ); } + + (scene as Scene).EventManager.TriggerOnChatToClients( + fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); } static private Vector3 CenterOfRegion = new Vector3(128, 128, 30); @@ -269,6 +277,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); + HashSet receiverIDs = new HashSet(); + ((Scene)c.Scene).ForEachScenePresence( delegate(ScenePresence presence) { @@ -286,16 +296,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, (byte)sourceType, (byte)ChatAudibleLevel.Fully); + receiverIDs.Add(presence.UUID); }); + + (c.Scene as Scene).EventManager.TriggerOnChatToClients( + fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); } - - protected virtual void TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, + /// + /// Try to send a message to the given presence + /// + /// The receiver + /// + /// /param> + /// + /// + /// + /// + /// + /// true if the message was sent to the receiver, false if it was not sent due to failing a + /// precondition + protected virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, UUID fromAgentID, string fromName, ChatTypeEnum type, string message, ChatSourceType src) { // don't send stuff to child agents - if (presence.IsChildAgent) return; + if (presence.IsChildAgent) return false; Vector3 fromRegionPos = fromPos + regionPos; Vector3 toRegionPos = presence.AbsolutePosition + @@ -308,12 +334,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat type == ChatTypeEnum.Say && dis > m_saydistance || type == ChatTypeEnum.Shout && dis > m_shoutdistance) { - return; + return false; } // TODO: should change so the message is sent through the avatar rather than direct to the ClientView presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, - fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully); + fromAgentID, (byte)src, (byte)ChatAudibleLevel.Fully); + + return true; } } } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 437b91a71b..4feb3fc3de 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -292,6 +292,17 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ChatFromClientEvent(Object sender, OSChatMessage chat); public event ChatFromClientEvent OnChatFromClient; + /// + /// ChatToClientsEvent is triggered via ChatModule (or + /// substitutes thereof) when a chat message is actually sent to clients. Clients will only be sent a + /// received chat message if they satisfy various conditions (within audible range, etc.) + /// + public delegate void ChatToClientsEvent( + UUID senderID, HashSet receiverIDs, + string message, ChatTypeEnum type, Vector3 fromPos, string fromName, + ChatSourceType src, ChatAudibleLevel level); + public event ChatToClientsEvent OnChatToClients; + /// /// ChatBroadcastEvent is called via Scene when a broadcast chat message /// from world comes in @@ -1603,6 +1614,30 @@ namespace OpenSim.Region.Framework.Scenes } } } + + public void TriggerOnChatToClients( + UUID senderID, HashSet receiverIDs, + string message, ChatTypeEnum type, Vector3 fromPos, string fromName, + ChatSourceType src, ChatAudibleLevel level) + { + ChatToClientsEvent handler = OnChatToClients; + if (handler != null) + { + foreach (ChatToClientsEvent d in handler.GetInvocationList()) + { + try + { + d(senderID, receiverIDs, message, type, fromPos, fromName, src, level); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[EVENT MANAGER]: Delegate for TriggerOnChatToClients failed - continuing. {0} {1}", + e.Message, e.StackTrace); + } + } + } + } public void TriggerOnChatBroadcast(Object sender, OSChatMessage chat) { From 460b9fffe5e0d5f7f339ce490619067677b4136f Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 18:39:40 +0100 Subject: [PATCH 33/51] write IAR control file first in the archive rather than last --- .../Inventory/Archiver/InventoryArchiveWriteRequest.cs | 10 ++++++---- .../World/Archiver/ArchiveWriteRequestPreparation.cs | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index bae5a7a289..f385a2a2a8 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -123,9 +123,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver try { - // We're almost done. Just need to write out the control file now - m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p1ControlFile()); - m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); m_archiveWriter.Close(); } catch (Exception e) @@ -216,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver public void Execute() { try - { + { InventoryFolderBase inventoryFolder = null; InventoryItemBase inventoryItem = null; InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); @@ -277,6 +274,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_archiveWriter = new TarArchiveWriter(m_saveStream); + // Write out control file. This has to be done first so that subsequent loaders will see this file first + // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this + m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p1ControlFile()); + m_log.InfoFormat("[INVENTORY ARCHIVER]: Added control file to archive."); + if (inventoryFolder != null) { m_log.DebugFormat( diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 43789af9ec..1687d06350 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -171,7 +171,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); - // Write out control file + // Write out control file. This has to be done first so that subsequent loaders will see this file first + // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p2ControlFile(options)); m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); From 772dbf59f37959a61681b487ded412ebdda8041a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 18:47:38 +0100 Subject: [PATCH 34/51] slightly simplify oar control file loading code --- .../World/Archiver/ArchiveReadRequest.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index f1f5258d1d..9192f43969 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -483,15 +483,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// private void LoadControlFile(string path, byte[] data) { - //Create the XmlNamespaceManager. - NameTable nt = new NameTable(); - XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt); - - // Create the XmlParserContext. + XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); - - XmlTextReader xtr - = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); + XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; @@ -530,10 +524,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString(); } } - } currentRegionSettings.Save(); } } -} +} \ No newline at end of file From 607c07b4aab2a194102832a1e380cfbabe11d078 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 19:24:42 +0100 Subject: [PATCH 35/51] start parsing iar control file This change requires a prebuild[.sh|.bat] since a System.Xml.Linq reference is added to prebuild.xml --- .../Archiver/InventoryArchiveReadRequest.cs | 20 ++++++++++++++++++- .../World/Archiver/ArchiveReadRequest.cs | 2 +- prebuild.xml | 1 + 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index c1df827069..2beea8ef6f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -33,6 +33,7 @@ using System.Reflection; using System.Threading; using System.Text; using System.Xml; +using System.Xml.Linq; using log4net; using OpenMetaverse; using OpenSim.Framework; @@ -133,7 +134,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver while ((data = archive.ReadEntry(out filePath, out entryType)) != null) { - if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + if (filePath == ArchiveConstants.CONTROL_FILE_PATH) + { + LoadControlFile(filePath, data); + } + else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) { if (LoadAsset(filePath, data)) successfulAssetRestores++; @@ -461,5 +466,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } } + + /// + /// Load control file + /// + /// + /// + protected void LoadControlFile(string path, byte[] data) + { + XDocument doc = XDocument.Parse(Encoding.ASCII.GetString(data)); + XElement archiveElement = doc.Element("archive"); + int.Parse(archiveElement.Attribute("major_version").Value); + int.Parse(archiveElement.Attribute("minor_version").Value); + } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 9192f43969..087d3dfed0 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -481,7 +481,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// /// - private void LoadControlFile(string path, byte[] data) + protected void LoadControlFile(string path, byte[] data) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); diff --git a/prebuild.xml b/prebuild.xml index b28d22697f..dd4a5769e7 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1387,6 +1387,7 @@ + From bdd6857006906227470e296161483a7839cb8b91 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 19:30:15 +0100 Subject: [PATCH 36/51] Implement guard against trying to load incompatible version IARs --- .../Archiver/InventoryArchiveReadRequest.cs | 21 +++++++++++++++++-- .../World/Archiver/ArchiveReadRequest.cs | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 2beea8ef6f..55005572ba 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -51,6 +51,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// + /// The maximum major version of archive that we can read. Minor versions shouldn't need a max number since version + /// bumps here should be compatible. + /// + public static int MAX_MAJOR_VERSION = 0; + protected TarArchiveReader archive; private UserAccount m_userInfo; @@ -476,8 +482,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { XDocument doc = XDocument.Parse(Encoding.ASCII.GetString(data)); XElement archiveElement = doc.Element("archive"); - int.Parse(archiveElement.Attribute("major_version").Value); - int.Parse(archiveElement.Attribute("minor_version").Value); + int majorVersion = int.Parse(archiveElement.Attribute("major_version").Value); + int minorVersion = int.Parse(archiveElement.Attribute("minor_version").Value); + string version = string.Format("{0}.{1}", majorVersion, minorVersion); + + if (majorVersion > MAX_MAJOR_VERSION) + { + throw new Exception( + string.Format( + "The IAR you are trying to load has major version number of {0} but this version of OpenSim can only load IARs with major version number {1} and below", + majorVersion, MAX_MAJOR_VERSION)); + } + + m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 087d3dfed0..117b2fd2fc 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// - /// The maximum major version of OAR that we can read. Minor versions shouldn't need a number since version + /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version /// bumps here should be compatible. /// public static int MAX_MAJOR_VERSION = 0; From a7a8fdc7dafb01f9c7689cdc95add52446a16d89 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 19:34:06 +0100 Subject: [PATCH 37/51] print IAR version number on console when saving --- .../Inventory/Archiver/InventoryArchiveWriteRequest.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index f385a2a2a8..249a8b4b9c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -401,13 +401,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// public static string Create0p1ControlFile() { + int majorVersion = 0, minorVersion = 1; + + m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); + StringWriter sw = new StringWriter(); XmlTextWriter xtw = new XmlTextWriter(sw); xtw.Formatting = Formatting.Indented; xtw.WriteStartDocument(); xtw.WriteStartElement("archive"); - xtw.WriteAttributeString("major_version", "0"); - xtw.WriteAttributeString("minor_version", "1"); + xtw.WriteAttributeString("major_version", majorVersion.ToString()); + xtw.WriteAttributeString("minor_version", minorVersion.ToString()); xtw.WriteEndElement(); xtw.Flush(); From 6d7ce630852fb43d1eb586190425c380b84d6dec Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 21:12:22 +0100 Subject: [PATCH 38/51] Allow OARs and IARs to save and load meshes. Save and reload appears okay for the duck mesh at https://collada.org/owl/download.php?sess=0&parent=126&expand=1&order=name&curview=0&binary=1&id=698/ However, one attempt at trying to load a more complicated scene failed (errors on console, only triangles appearing in mesh viewer). Not sure if this is really and OAR load problem. Needs more investigation. --- OpenSim/Framework/Serialization/ArchiveConstants.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs index 7a9b33dc8c..2c5e0018ec 100644 --- a/OpenSim/Framework/Serialization/ArchiveConstants.cs +++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs @@ -112,6 +112,7 @@ namespace OpenSim.Framework.Serialization ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LostAndFoundFolder] = ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"; // Not sure if we'll ever see this ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLBytecode] = ASSET_EXTENSION_SEPARATOR + "bytecode.lso"; ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.LSLText] = ASSET_EXTENSION_SEPARATOR + "script.lsl"; + ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Mesh] = ASSET_EXTENSION_SEPARATOR + "mesh.llmesh"; ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Notecard] = ASSET_EXTENSION_SEPARATOR + "notecard.txt"; ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Object] = ASSET_EXTENSION_SEPARATOR + "object.xml"; ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.RootFolder] = ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"; // Not sure if we'll ever see this @@ -135,6 +136,7 @@ namespace OpenSim.Framework.Serialization EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "lostandfoundfolder.txt"] = (sbyte)AssetType.LostAndFoundFolder; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bytecode.lso"] = (sbyte)AssetType.LSLBytecode; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "script.lsl"] = (sbyte)AssetType.LSLText; + EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "mesh.llmesh"] = (sbyte)AssetType.Mesh; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "notecard.txt"] = (sbyte)AssetType.Notecard; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "object.xml"] = (sbyte)AssetType.Object; EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "rootfolder.txt"] = (sbyte)AssetType.RootFolder; From d58967be580afa9c349c29261fd7f845faf558e4 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 21:28:10 +0100 Subject: [PATCH 39/51] Fix llParcelMediaCommandList() so that it applies commands only to the parcel that the script is in, not all parcels. Patch from http://opensimulator.org/mantis/view.php?id=2738 Thanks snoopy and fineman. --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e6092d4723..59a36187cf 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9101,10 +9101,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // do that one last, it will cause a ParcelPropertiesUpdate landObject.SetMediaUrl(url); - // now send to all (non-child) agents + // now send to all (non-child) agents in the parcel World.ForEachScenePresence(delegate(ScenePresence sp) { - if (!sp.IsChildAgent) + if (!sp.IsChildAgent && (sp.currentParcelUUID == landData.GlobalID)) { sp.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, landData.MediaID, @@ -9134,10 +9134,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // the commandList contained a start/stop/... command, too if (presence == null) { - // send to all (non-child) agents + // send to all (non-child) agents in the parcel World.ForEachScenePresence(delegate(ScenePresence sp) { - if (!sp.IsChildAgent) + if (!sp.IsChildAgent && (sp.currentParcelUUID == landData.GlobalID)) { sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? (ParcelMediaCommandEnum)commandToSend, From cddcb53b177cfa18a00db2320929de455c8e0e58 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 23:34:37 +0100 Subject: [PATCH 40/51] Revert "* remove some spurious debug info" This reverts commit 017b83d0a3e3ac6a1c8bc86b9bef1ee47cba059e. --- .../Servers/HttpServer/BaseHttpServer.cs | 10 +++---- .../Region/Framework/Scenes/ScenePresence.cs | 2 -- .../Hypergrid/GatekeeperServiceConnector.cs | 30 +++++++++---------- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 0c1e5e013b..47e86ad56b 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -348,7 +348,7 @@ namespace OpenSim.Framework.Servers.HttpServer { try { - //m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); + m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); @@ -376,11 +376,11 @@ namespace OpenSim.Framework.Servers.HttpServer string path = request.RawUrl; string handlerKey = GetHandlerKey(request.HttpMethod, path); - //m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); + m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); if (TryGetStreamHandler(handlerKey, out requestHandler)) { - //m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); + m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler. byte[] buffer = null; @@ -395,7 +395,7 @@ namespace OpenSim.Framework.Servers.HttpServer } else if (requestHandler is IGenericHTTPHandler) { - //m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); + m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler; Stream requestStream = request.InputStream; @@ -422,7 +422,7 @@ namespace OpenSim.Framework.Servers.HttpServer foreach (string headername in rHeaders) { - //m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); + m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); headervals[headername] = request.Headers[headername]; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index c223b4b50d..13d99643bf 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2976,8 +2976,6 @@ namespace OpenSim.Region.Framework.Scenes public void CopyTo(AgentData cAgent) { - cAgent.CallbackURI = m_callbackURI; - cAgent.AgentID = UUID; cAgent.RegionID = Scene.RegionInfo.RegionID; diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 4231be1f66..2b19b8709f 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -116,19 +116,19 @@ namespace OpenSim.Services.Connectors.Hypergrid if (success) { UUID.TryParse((string)hash["uuid"], out regionID); - //m_log.Debug(">> HERE, uuid: " + regionID); + m_log.Debug(">> HERE, uuid: " + regionID); if ((string)hash["handle"] != null) { realHandle = Convert.ToUInt64((string)hash["handle"]); - //m_log.Debug(">> HERE, realHandle: " + realHandle); + m_log.Debug(">> HERE, realHandle: " + realHandle); } if (hash["region_image"] != null) { imageURL = (string)hash["region_image"]; - //m_log.Debug(">> HERE, imageURL: " + imageURL); + m_log.Debug(">> HERE, imageURL: " + imageURL); } if (hash["external_name"] != null) { externalName = (string)hash["external_name"]; - //m_log.Debug(">> HERE, externalName: " + externalName); + m_log.Debug(">> HERE, externalName: " + externalName); } } @@ -191,7 +191,7 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_region", paramList); - //m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); XmlRpcResponse response = null; try { @@ -199,7 +199,7 @@ namespace OpenSim.Services.Connectors.Hypergrid } catch (Exception e) { - //m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message); return null; } @@ -210,8 +210,8 @@ namespace OpenSim.Services.Connectors.Hypergrid } hash = (Hashtable)response.Value; - //foreach (Object o in hash) - // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + foreach (Object o in hash) + m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); try { bool success = false; @@ -221,41 +221,41 @@ namespace OpenSim.Services.Connectors.Hypergrid GridRegion region = new GridRegion(); UUID.TryParse((string)hash["uuid"], out region.RegionID); - //m_log.Debug(">> HERE, uuid: " + 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); + 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); + m_log.Debug(">> HERE, y: " + region.RegionLocY); } if (hash["region_name"] != null) { region.RegionName = (string)hash["region_name"]; - //m_log.Debug(">> HERE, region_name: " + region.RegionName); + m_log.Debug(">> HERE, region_name: " + region.RegionName); } if (hash["hostname"] != null) region.ExternalHostName = (string)hash["hostname"]; - //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); + m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); if (hash["http_port"] != null) { uint p = 0; UInt32.TryParse((string)hash["http_port"], out p); region.HttpPort = p; - //m_log.Debug(">> HERE, http_port: " + region.HttpPort); + m_log.Debug(">> HERE, http_port: " + region.HttpPort); } 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); - //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); + m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); } // Successful return From a490b34b6e584119312bd1b9ee8c30c4b9f02c62 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 23:34:44 +0100 Subject: [PATCH 41/51] Revert "* more url / hg cleanup" This reverts commit 58f75fa19d9aea18283ecdbd44559efb81781c9d. --- OpenSim/Framework/Capabilities/CapsUtil.cs | 2 +- OpenSim/Framework/RegionInfo.cs | 31 ++--------------- .../EntityTransfer/EntityTransferModule.cs | 34 +++++++++++++------ .../InterGrid/OpenGridProtocolModule.cs | 4 +-- .../Handlers/Hypergrid/HomeAgentHandlers.cs | 2 -- .../Services/GridService/HypergridLinker.cs | 18 +++++++--- .../HypergridService/UserAgentService.cs | 1 - OpenSim/Services/Interfaces/IGridService.cs | 9 +---- 8 files changed, 45 insertions(+), 56 deletions(-) diff --git a/OpenSim/Framework/Capabilities/CapsUtil.cs b/OpenSim/Framework/Capabilities/CapsUtil.cs index faf2708541..0334e4b4a2 100644 --- a/OpenSim/Framework/Capabilities/CapsUtil.cs +++ b/OpenSim/Framework/Capabilities/CapsUtil.cs @@ -41,7 +41,7 @@ namespace OpenSim.Framework.Capabilities /// public static string GetCapsSeedPath(string capsObjectPath) { - return "CAPS/" + capsObjectPath + "0000/"; + return "/CAPS/" + capsObjectPath + "0000/"; } /// diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 73b8bd0120..949a28985e 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -115,13 +115,7 @@ namespace OpenSim.Framework /// public string ServerURI { - get { - if ( m_serverURI != string.Empty ) { - return m_serverURI; - } else { - return "http://" + m_externalHostName + ":" + m_httpPort + "/"; - } - } + get { return m_serverURI; } set { if ( value.EndsWith("/") ) { m_serverURI = value; @@ -153,7 +147,6 @@ namespace OpenSim.Framework public SimpleRegionInfo() { - m_serverURI = string.Empty; } public SimpleRegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) @@ -163,7 +156,6 @@ namespace OpenSim.Framework m_internalEndPoint = internalEndPoint; m_externalHostName = externalUri; - m_serverURI = string.Empty; } public SimpleRegionInfo(uint regionLocX, uint regionLocY, string externalUri, uint port) @@ -174,7 +166,6 @@ namespace OpenSim.Framework m_externalHostName = externalUri; m_internalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int) port); - m_serverURI = string.Empty; } public SimpleRegionInfo(RegionInfo ConvertFrom) @@ -464,7 +455,6 @@ namespace OpenSim.Framework configMember = new ConfigurationMember(xmlNode, description, loadConfigurationOptions, handleIncomingConfiguration, !skipConsoleConfig); configMember.performConfigurationRetrieve(); - m_serverURI = string.Empty; } public RegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) @@ -474,12 +464,10 @@ namespace OpenSim.Framework m_internalEndPoint = internalEndPoint; m_externalHostName = externalUri; - m_serverURI = string.Empty; } public RegionInfo() { - m_serverURI = string.Empty; } public EstateSettings EstateSettings @@ -569,23 +557,10 @@ namespace OpenSim.Framework /// /// A well-formed URI for the host region server (namely "http://" + ExternalHostName) /// - public string ServerURI { - get { - if ( m_serverURI != string.Empty ) { - return m_serverURI; - } else { - return "http://" + m_externalHostName + ":" + m_httpPort + "/"; - } - } - set { - if ( value.EndsWith("/") ) { - m_serverURI = value; - } else { - m_serverURI = value + '/'; - } - } + get { return m_serverURI; } + set { m_serverURI = value; } } public string RegionName diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 54cc80f384..3791e1df6f 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -327,21 +327,34 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // OK, it got this agent. Let's close some child agents sp.CloseChildAgents(newRegionX, newRegionY); - IClientIPEndpoint ipepClient; + if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY)) { //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); + #region IP Translation for NAT - // Uses ipepClient above + IClientIPEndpoint ipepClient; if (sp.ClientView.TryGet(out ipepClient)) { - endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); + capsPath + = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + } + else + { + capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } #endregion - capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); 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, @@ -360,7 +373,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer else { agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); - capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + capsPath = finalDestination.ServerURI + "/CAPS/" + agentCircuit.CapsPath + "0000/"; } // Expect avatar crossing is a heavy-duty function at the destination. @@ -493,8 +506,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) { - agent.CallbackURI = region.ServerURI + "agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; - m_log.Debug("Set callback URL to " + agent.CallbackURI); + agent.CallbackURI = region.ServerURI + "/agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; } @@ -820,7 +832,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (isFlying) cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; cAgent.CallbackURI = m_scene.RegionInfo.ServerURI + - "agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; + "/agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) { @@ -845,7 +857,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer neighbourRegion.RegionHandle); return agent; } - string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); + // TODO Should construct this behind a method + string capsPath = + neighbourRegion.ServerURI + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/"; m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); @@ -1164,7 +1178,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer y = y / Constants.RegionSize; m_log.Info("[ENTITY TRANSFER MODULE]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")"); - string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath); + string capsPath = reg.ServerURI + "/CAPS/" + a.CapsPath + "0000/"; string reason = String.Empty; diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs index 2dd7767d76..fd0e879e05 100644 --- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs +++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs @@ -595,12 +595,12 @@ namespace OpenSim.Region.CoreModules.InterGrid // DEPRECATED responseMap["seed_capability"] = OSD.FromString( - regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + "/" + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); + regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); // REPLACEMENT responseMap["region_seed_capability"] = OSD.FromString( - regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + "/" + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); + regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); responseMap["rez_avatar"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); responseMap["rez_avatar/rez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs index a1bcba6a37..f64a07973e 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs @@ -124,7 +124,6 @@ namespace OpenSim.Server.Handlers.Hypergrid UUID uuid = UUID.Zero; string regionname = string.Empty; string gatekeeper_host = string.Empty; - string server_uri = string.Empty; int gatekeeper_port = 0; IPEndPoint client_ipaddress = null; @@ -174,7 +173,6 @@ namespace OpenSim.Server.Handlers.Hypergrid destination.RegionLocX = x; destination.RegionLocY = y; destination.RegionName = regionname; - AgentCircuitData aCircuit = new AgentCircuitData(); try diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 74e864b8aa..11df7e0b73 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -198,7 +198,20 @@ namespace OpenSim.Services.GridService return null; } + + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, string serverURI, out GridRegion regInfo, out string reason) + { + return TryCreateLink(scopeID, xloc, yloc, externalRegionName, 0, null, serverURI, out regInfo, out reason); + } + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) + { + return TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, out regInfo, out reason); + } + + // From the command line and the 2 above + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, + string externalRegionName, uint externalPort, string externalHostName, string serverURI, out GridRegion regInfo, out string reason) { m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0}:{1}:{2}, in {3}-{4}", externalHostName, externalPort, externalRegionName, xloc, yloc); @@ -213,11 +226,8 @@ namespace OpenSim.Services.GridService // Big HACK for Simian Grid !!! // We need to clean up all URLs used in OpenSim !!! - if (externalHostName.Contains("/")) { + if (externalHostName.Contains("/")) regInfo.ServerURI = externalHostName; - } else { - regInfo.ServerURI = "http://" + externalHostName + ":" + externalPort.ToString(); - } try { diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index aed2dc8bd2..d5dda115c8 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -136,7 +136,6 @@ namespace OpenSim.Services.HypergridService m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ExternalHostName +":"+ gatekeeper.HttpPort); - m_log.Debug("gatekeeper serveruri -> " + gatekeeper.ServerURI ); // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination GridRegion region = new GridRegion(gatekeeper); diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index 6d3bff7683..bf441e6076 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -115,13 +115,7 @@ namespace OpenSim.Services.Interfaces /// public string ServerURI { - get { - if ( m_serverURI != string.Empty ) { - return m_serverURI; - } else { - return "http://" + m_externalHostName + ":" + m_httpPort + "/"; - } - } + get { return m_serverURI; } set { if ( value.EndsWith("/") ) { m_serverURI = value; @@ -176,7 +170,6 @@ namespace OpenSim.Services.Interfaces public GridRegion() { - m_serverURI = string.Empty; } public GridRegion(int regionLocX, int regionLocY, IPEndPoint internalEndPoint, string externalUri) From 783b1b548f24b002f09cf2ceb0bdab76afed0fab Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 23:34:53 +0100 Subject: [PATCH 42/51] Revert "* additional serveruri cleanup" This reverts commit 19119d7705f8381a3c207d0e64a23243215a12b9. --- OpenSim/Region/Application/OpenSimBase.cs | 2 +- .../InstantMessage/MessageTransferModule.cs | 6 ++-- .../World/WorldMap/WorldMapModule.cs | 2 +- .../Hypergrid/GatekeeperServiceConnector.cs | 14 +++++---- .../Simulation/SimulationServiceConnector.cs | 10 ++++++- OpenSim/Services/GridService/GridService.cs | 2 +- .../Services/GridService/HypergridLinker.cs | 9 ++---- .../LLLoginService/LLLoginResponse.cs | 29 ++++++++++++++++++- 8 files changed, 54 insertions(+), 20 deletions(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 904a50c799..f30a8504fe 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -328,7 +328,7 @@ namespace OpenSim // set initial ServerURI regionInfo.HttpPort = m_httpServerPort; - regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort.ToString() + "/"; + regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort.ToString(); regionInfo.osSecret = m_osSecret; diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index fdc48c6b69..918fa04143 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -599,7 +599,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage try { - XmlRpcResponse GridResp = GridReq.Send(reginfo.ServerURI, 3000); + XmlRpcResponse GridResp = GridReq.Send("http://" + reginfo.ExternalHostName + ":" + reginfo.HttpPort, 3000); Hashtable responseData = (Hashtable)GridResp.Value; @@ -621,8 +621,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } catch (WebException e) { - m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0}} the host didn't respond ({2})", - reginfo.ServerURI, e.Message); + m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to http://{0}:{1} the host didn't respond ({2})", + reginfo.ExternalHostName, reginfo.HttpPort, e.Message); } return false; diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index fdbbccfbab..3ce964af49 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -579,7 +579,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (mreg != null) { - httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString(); + httpserver = "http://" + mreg.ExternalEndPoint.Address.ToString() + ":" + mreg.HttpPort + "/MAP/MapItems/" + regionhandle.ToString(); lock (m_cachedRegionMapItemsAddress) { if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 2b19b8709f..89a8f7a1b8 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -63,12 +63,12 @@ namespace OpenSim.Services.Connectors.Hypergrid protected override string AgentPath() { - return "foreignagent/"; + return "/foreignagent/"; } protected override string ObjectPath() { - return "foreignobject/"; + return "/foreignobject/"; } public bool LinkRegion(GridRegion info, out UUID regionID, out ulong realHandle, out string externalName, out string imageURL, out string reason) @@ -86,11 +86,12 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("link_region", paramList); - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Linking to " + info.ServerURI); + string uri = "http://" + ((info.ServerURI != null && info.ServerURI != string.Empty && !info.ServerURI.StartsWith("http:")) ? info.ServerURI : info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Linking to " + uri); XmlRpcResponse response = null; try { - response = request.Send(info.ServerURI, 10000); + response = request.Send(uri, 10000); } catch (Exception e) { @@ -191,11 +192,12 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_region", paramList); - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); + string uri = "http://" + ((gatekeeper.ServerURI != null && gatekeeper.ServerURI != string.Empty && !gatekeeper.ServerURI.StartsWith("http:")) ? gatekeeper.ServerURI : gatekeeper.ExternalEndPoint.Address + ":" + gatekeeper.HttpPort + "/"); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + uri); XmlRpcResponse response = null; try { - response = request.Send(gatekeeper.ServerURI, 10000); + response = request.Send(uri, 10000); } catch (Exception e) { diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index c4284eb920..07839d3b59 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -72,7 +72,7 @@ namespace OpenSim.Services.Connectors.Simulation protected virtual string AgentPath() { - return "agent/"; + return "/agent/"; } public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) @@ -106,6 +106,8 @@ namespace OpenSim.Services.Connectors.Simulation string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; + //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri); + AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri); AgentCreateRequest.Method = "POST"; AgentCreateRequest.ContentType = "application/json"; @@ -259,6 +261,7 @@ namespace OpenSim.Services.Connectors.Simulation { // Eventually, we want to use a caps url instead of the agentID string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; + //Console.WriteLine(" >>> DoAgentUpdateCall <<< " + uri); HttpWebRequest ChildUpdateRequest = (HttpWebRequest)WebRequest.Create(uri); ChildUpdateRequest.Method = "PUT"; @@ -357,6 +360,7 @@ namespace OpenSim.Services.Connectors.Simulation agent = null; // Eventually, we want to use a caps url instead of the agentID string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + //Console.WriteLine(" >>> DoRetrieveRootAgentCall <<< " + uri); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "GET"; @@ -377,6 +381,7 @@ namespace OpenSim.Services.Connectors.Simulation sr = new StreamReader(webResponse.GetResponseStream()); reply = sr.ReadToEnd().Trim(); + //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: ChilAgentUpdate reply was " + reply); } catch (WebException ex) @@ -397,6 +402,7 @@ namespace OpenSim.Services.Connectors.Simulation OSDMap args = Util.GetOSDMap(reply); if (args == null) { + //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: Error getting OSDMap from reply"); return false; } @@ -405,6 +411,7 @@ namespace OpenSim.Services.Connectors.Simulation return true; } + //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: DoRetrieveRootAgentCall returned status " + webResponse.StatusCode); return false; } @@ -448,6 +455,7 @@ namespace OpenSim.Services.Connectors.Simulation { string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri); WebRequest request = WebRequest.Create(uri); request.Method = "DELETE"; diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index 125c2be8cf..e7988d6e93 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -479,7 +479,7 @@ namespace OpenSim.Services.GridService OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); MainConsole.Instance.Output(String.Format("{0,-20} {1}\n{2,-20} {3}\n{4,-39} {5}\n\n", r.RegionName, r.RegionID, - String.Format("{0},{1}", r.posX, r.posY), r.Data["serverURI"], + String.Format("{0},{1}", r.posX, r.posY), "http://" + r.Data["serverIP"].ToString() + ":" + r.Data["serverPort"].ToString(), r.Data["owner_uuid"].ToString(), flags.ToString())); } return; diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 11df7e0b73..757ae80a70 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -199,14 +199,11 @@ namespace OpenSim.Services.GridService return null; } - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, string serverURI, out GridRegion regInfo, out string reason) - { - return TryCreateLink(scopeID, xloc, yloc, externalRegionName, 0, null, serverURI, out regInfo, out reason); - } - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, + string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) { - return TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, out regInfo, out reason); + TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, regInfo, reason); } // From the command line and the 2 above diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index f985ab21ba..0da1715849 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -333,7 +333,34 @@ namespace OpenSim.Services.LLLoginService private void FillOutSeedCap(AgentCircuitData aCircuit, GridRegion destination, IPEndPoint ipepClient) { - SeedCapability = destination.ServerURI + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); + string capsSeedPath = String.Empty; + + // Don't use the following! It Fails for logging into any region not on the same port as the http server! + // Kept here so it doesn't happen again! + // response.SeedCapability = regionInfo.ServerURI + capsSeedPath; + + #region IP Translation for NAT + if (ipepClient != null) + { + capsSeedPath + = "http://" + + NetworkUtil.GetHostFor(ipepClient.Address, destination.ExternalHostName) + + ":" + + destination.HttpPort + + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); + } + else + { + capsSeedPath + = "http://" + + destination.ExternalHostName + + ":" + + destination.HttpPort + + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); + } + #endregion + + SeedCapability = capsSeedPath; } private void SetDefaultValues() From 8f34e46d7449be1c29419a232a8f7f1e5918f03c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 23:35:01 +0100 Subject: [PATCH 43/51] Revert "* refactor refactor refactor ServerURI 4 lyfe" This reverts commit 55974df14b6d64c1e1f9e386a3eacce3ba86dc98. --- OpenSim/Framework/RegionInfo.cs | 8 +--- .../Servers/HttpServer/BaseHttpServer.cs | 10 ++--- OpenSim/Region/Application/OpenSimBase.cs | 2 +- .../EntityTransfer/EntityTransferModule.cs | 27 ++++++++--- .../World/WorldMap/WorldMapModule.cs | 2 +- .../Hypergrid/GatekeeperServiceConnector.cs | 31 +++++-------- .../Connectors/Land/LandServiceConnector.cs | 3 +- .../Neighbour/NeighbourServiceConnector.cs | 2 +- .../SimianGrid/SimianGridServiceConnector.cs | 4 +- .../Simulation/SimulationServiceConnector.cs | 45 ++++++++++++++++--- .../Services/GridService/HypergridLinker.cs | 14 +----- .../HypergridService/GatekeeperService.cs | 2 +- .../HypergridService/UserAgentService.cs | 8 ++-- OpenSim/Services/Interfaces/IGridService.cs | 8 +--- 14 files changed, 94 insertions(+), 72 deletions(-) diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 949a28985e..08d5398a18 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -116,13 +116,7 @@ namespace OpenSim.Framework public string ServerURI { get { return m_serverURI; } - set { - if ( value.EndsWith("/") ) { - m_serverURI = value; - } else { - m_serverURI = value + '/'; - } - } + set { m_serverURI = value; } } protected string m_serverURI; diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 47e86ad56b..ba8c1941a8 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -348,7 +348,7 @@ namespace OpenSim.Framework.Servers.HttpServer { try { - m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); +// m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); @@ -376,11 +376,11 @@ namespace OpenSim.Framework.Servers.HttpServer string path = request.RawUrl; string handlerKey = GetHandlerKey(request.HttpMethod, path); - m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); +// m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); if (TryGetStreamHandler(handlerKey, out requestHandler)) { - m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); + //m_log.Debug("[BASE HTTP SERVER]: Found Stream Handler"); // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler. byte[] buffer = null; @@ -395,7 +395,7 @@ namespace OpenSim.Framework.Servers.HttpServer } else if (requestHandler is IGenericHTTPHandler) { - m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); + //m_log.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler"); IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler; Stream requestStream = request.InputStream; @@ -422,7 +422,7 @@ namespace OpenSim.Framework.Servers.HttpServer foreach (string headername in rHeaders) { - m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); + //m_log.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]); headervals[headername] = request.Headers[headername]; } diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index f30a8504fe..74ad1685f9 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -327,8 +327,8 @@ namespace OpenSim //regionInfo.originRegionID = regionInfo.RegionID; // set initial ServerURI + regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.InternalEndPoint.Port; regionInfo.HttpPort = m_httpServerPort; - regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort.ToString(); regionInfo.osSecret = m_osSecret; diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 3791e1df6f..38fff1cab3 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -337,11 +337,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (sp.ClientView.TryGet(out ipepClient)) { capsPath - = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + = "http://" + + NetworkUtil.GetHostFor(ipepClient.EndPoint, finalDestination.ExternalHostName) + + ":" + + finalDestination.HttpPort + + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } else { - capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + capsPath + = "http://" + + finalDestination.ExternalHostName + + ":" + + finalDestination.HttpPort + + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } #endregion @@ -373,7 +382,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer else { agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); - capsPath = finalDestination.ServerURI + "/CAPS/" + agentCircuit.CapsPath + "0000/"; + capsPath = "http://" + finalDestination.ExternalHostName + ":" + finalDestination.HttpPort + + "/CAPS/" + agentCircuit.CapsPath + "0000/"; } // Expect avatar crossing is a heavy-duty function at the destination. @@ -506,7 +516,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) { - agent.CallbackURI = region.ServerURI + "/agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; + agent.CallbackURI = "http://" + region.ExternalHostName + ":" + region.HttpPort + + "/agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; } @@ -831,7 +842,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer cAgent.Position = pos; if (isFlying) cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; - cAgent.CallbackURI = m_scene.RegionInfo.ServerURI + + cAgent.CallbackURI = "http://" + m_scene.RegionInfo.ExternalHostName + ":" + m_scene.RegionInfo.HttpPort + "/agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) @@ -859,7 +870,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } // TODO Should construct this behind a method string capsPath = - neighbourRegion.ServerURI + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/"; + "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort + + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/"; m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); @@ -1178,7 +1190,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer y = y / Constants.RegionSize; m_log.Info("[ENTITY TRANSFER MODULE]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")"); - string capsPath = reg.ServerURI + "/CAPS/" + a.CapsPath + "0000/"; + string capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort + + "/CAPS/" + a.CapsPath + "0000/"; string reason = String.Empty; diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 3ce964af49..a182eeae7d 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -147,7 +147,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString(); regionimage = regionimage.Replace("-", ""); - m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "/index.php?method=" + regionimage); + m_log.Info("[WORLD MAP]: JPEG Map location: http://" + m_scene.RegionInfo.ExternalEndPoint.Address.ToString() + ":" + m_scene.RegionInfo.HttpPort.ToString() + "/index.php?method=" + regionimage); MainServer.Instance.AddHTTPHandler(regionimage, OnHTTPGetMapImage); MainServer.Instance.AddLLSDHandler( diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 89a8f7a1b8..479a80e297 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -108,8 +108,8 @@ namespace OpenSim.Services.Connectors.Hypergrid } hash = (Hashtable)response.Value; - foreach (Object o in hash) - m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); try { bool success = false; @@ -117,20 +117,16 @@ namespace OpenSim.Services.Connectors.Hypergrid if (success) { UUID.TryParse((string)hash["uuid"], out regionID); - m_log.Debug(">> HERE, uuid: " + regionID); + //m_log.Debug(">> HERE, uuid: " + uuid); if ((string)hash["handle"] != null) { realHandle = Convert.ToUInt64((string)hash["handle"]); - m_log.Debug(">> HERE, realHandle: " + realHandle); + //m_log.Debug(">> HERE, realHandle: " + realHandle); } - if (hash["region_image"] != null) { + if (hash["region_image"] != null) imageURL = (string)hash["region_image"]; - m_log.Debug(">> HERE, imageURL: " + imageURL); - } - if (hash["external_name"] != null) { + if (hash["external_name"] != null) externalName = (string)hash["external_name"]; - m_log.Debug(">> HERE, externalName: " + externalName); - } } } @@ -212,8 +208,8 @@ namespace OpenSim.Services.Connectors.Hypergrid } hash = (Hashtable)response.Value; - foreach (Object o in hash) - m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); try { bool success = false; @@ -223,41 +219,38 @@ namespace OpenSim.Services.Connectors.Hypergrid GridRegion region = new GridRegion(); UUID.TryParse((string)hash["uuid"], out region.RegionID); - m_log.Debug(">> HERE, uuid: " + 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); + //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); + //m_log.Debug(">> HERE, y: " + region.RegionLocY); } if (hash["region_name"] != null) { region.RegionName = (string)hash["region_name"]; - m_log.Debug(">> HERE, region_name: " + region.RegionName); + //m_log.Debug(">> HERE, name: " + region.RegionName); } if (hash["hostname"] != null) region.ExternalHostName = (string)hash["hostname"]; - m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); if (hash["http_port"] != null) { uint p = 0; UInt32.TryParse((string)hash["http_port"], out p); region.HttpPort = p; - m_log.Debug(">> HERE, http_port: " + region.HttpPort); } 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); - m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); } // Successful return diff --git a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs index 4b25ac819a..8143b5a89f 100644 --- a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs +++ b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs @@ -84,7 +84,8 @@ namespace OpenSim.Services.Connectors if (info != null) // just to be sure { XmlRpcRequest request = new XmlRpcRequest("land_data", paramList); - XmlRpcResponse response = request.Send(info.ServerURI, 10000); + string uri = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"; + XmlRpcResponse response = request.Send(uri, 10000); if (response.IsFault) { m_log.ErrorFormat("[LAND CONNECTOR]: remote call returned an error: {0}", response.FaultString); diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs index 9c57a40701..0a982f8d57 100644 --- a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs +++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs @@ -87,7 +87,7 @@ namespace OpenSim.Services.Connectors public bool DoHelloNeighbourCall(GridRegion region, RegionInfo thisRegion) { - string uri = region.ServerURI + "/region/" + thisRegion.RegionID + "/"; + string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/region/" + thisRegion.RegionID + "/"; //m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri); WebRequest HelloNeighbourRequest = WebRequest.Create(uri); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index 8076fab589..168b233893 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -145,6 +145,8 @@ namespace OpenSim.Services.Connectors.SimianGrid Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0); + string httpAddress = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort + "/"; + OSDMap extraData = new OSDMap { { "ServerURI", OSD.FromString(regionInfo.ServerURI) }, @@ -166,7 +168,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Name", regionInfo.RegionName }, { "MinPosition", minPosition.ToString() }, { "MaxPosition", maxPosition.ToString() }, - { "Address", regionInfo.ServerURI }, + { "Address", httpAddress }, { "Enabled", "1" }, { "ExtraData", OSDParser.SerializeJsonString(extraData) } }; diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 07839d3b59..a5f748f0c4 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -104,7 +104,24 @@ namespace OpenSim.Services.Connectors.Simulation return false; } - string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; + string uri = string.Empty; + + // HACK -- Simian grid make it work!!! + if (destination.ServerURI != null && destination.ServerURI != string.Empty && !destination.ServerURI.StartsWith("http:")) + uri = "http://" + destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; + else + { + try + { + uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + aCircuit.AgentID + "/"; + } + catch (Exception e) + { + m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent create. Reason: " + e.Message); + reason = e.Message; + return false; + } + } //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri); @@ -260,7 +277,16 @@ namespace OpenSim.Services.Connectors.Simulation private bool UpdateAgent(GridRegion destination, IAgentData cAgentData) { // Eventually, we want to use a caps url instead of the agentID - string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; + string uri = string.Empty; + try + { + uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + cAgentData.AgentID + "/"; + } + catch (Exception e) + { + m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent update. Reason: " + e.Message); + return false; + } //Console.WriteLine(" >>> DoAgentUpdateCall <<< " + uri); HttpWebRequest ChildUpdateRequest = (HttpWebRequest)WebRequest.Create(uri); @@ -359,7 +385,7 @@ namespace OpenSim.Services.Connectors.Simulation { agent = null; // Eventually, we want to use a caps url instead of the agentID - string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + string uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; //Console.WriteLine(" >>> DoRetrieveRootAgentCall <<< " + uri); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); @@ -453,7 +479,16 @@ namespace OpenSim.Services.Connectors.Simulation public bool CloseAgent(GridRegion destination, UUID id) { - string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + string uri = string.Empty; + try + { + uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + } + catch (Exception e) + { + m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent close. Reason: " + e.Message); + return false; + } //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri); @@ -503,7 +538,7 @@ namespace OpenSim.Services.Connectors.Simulation public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall) { string uri - = destination.ServerURI + ObjectPath() + sog.UUID + "/"; + = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + ObjectPath() + sog.UUID + "/"; //m_log.Debug(" >>> DoCreateObjectCall <<< " + uri); WebRequest ObjectCreateRequest = WebRequest.Create(uri); diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 757ae80a70..b86fb6f01c 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -127,7 +127,7 @@ namespace OpenSim.Services.GridService if (MainConsole.Instance != null) { MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region", - "link-region [] ", + "link-region :[:] ", "Link a hypergrid region", RunCommand); MainConsole.Instance.Commands.AddCommand("hypergrid", false, "unlink-region", "unlink-region or : ", @@ -200,15 +200,9 @@ namespace OpenSim.Services.GridService } - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, - string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) - { - TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, regInfo, reason); - } - // From the command line and the 2 above public bool TryCreateLink(UUID scopeID, int xloc, int yloc, - string externalRegionName, uint externalPort, string externalHostName, string serverURI, out GridRegion regInfo, out string reason) + string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) { m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0}:{1}:{2}, in {3}-{4}", externalHostName, externalPort, externalRegionName, xloc, yloc); @@ -515,16 +509,12 @@ namespace OpenSim.Services.GridService int xloc, yloc; uint externalPort; string externalHostName; - string serverURI; try { xloc = Convert.ToInt32(cmdparams[0]); yloc = Convert.ToInt32(cmdparams[1]); externalPort = Convert.ToUInt32(cmdparams[3]); externalHostName = cmdparams[2]; - if ( cmdparams.Length == 4 ) { - - } //internalPort = Convert.ToUInt32(cmdparams[4]); //remotingPort = Convert.ToUInt32(cmdparams[5]); } diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs index 9e961636ce..3f5c4f1400 100644 --- a/OpenSim/Services/HypergridService/GatekeeperService.cs +++ b/OpenSim/Services/HypergridService/GatekeeperService.cs @@ -157,7 +157,7 @@ namespace OpenSim.Services.HypergridService string regionimage = "regionImage" + region.RegionID.ToString(); regionimage = regionimage.Replace("-", ""); - imageURL = region.ServerURI + "index.php?method=" + regionimage; + imageURL = "http://" + region.ExternalHostName + ":" + region.HttpPort + "/index.php?method=" + regionimage; return true; } diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index d5dda115c8..eb6433cc6f 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -145,12 +145,12 @@ namespace OpenSim.Services.HypergridService region.RegionLocY = finalDestination.RegionLocY; // Generate a new service session - agentCircuit.ServiceSessionID = region.ServerURI + ";" + UUID.Random(); + agentCircuit.ServiceSessionID = "http://" + region.ExternalHostName + ":" + region.HttpPort + ";" + UUID.Random(); TravelingAgentInfo old = UpdateTravelInfo(agentCircuit, region); bool success = false; string myExternalIP = string.Empty; - string gridName = gatekeeper.ServerURI; + string gridName = "http://" + gatekeeper.ExternalHostName + ":" + gatekeeper.HttpPort; if (m_GridName == gridName) success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); else @@ -159,7 +159,7 @@ namespace OpenSim.Services.HypergridService if (!success) { m_log.DebugFormat("[USER AGENT SERVICE]: Unable to login user {0} {1} to grid {2}, reason: {3}", - agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason); + agentCircuit.firstname, agentCircuit.lastname, region.ExternalHostName + ":" + region.HttpPort, reason); // restore the old travel info lock (m_TravelingAgents) @@ -210,7 +210,7 @@ namespace OpenSim.Services.HypergridService m_TravelingAgents[agentCircuit.SessionID] = travel; } travel.UserID = agentCircuit.AgentID; - travel.GridExternalName = region.ServerURI; + travel.GridExternalName = "http://" + region.ExternalHostName + ":" + region.HttpPort; travel.ServiceToken = agentCircuit.ServiceSessionID; if (old != null) travel.ClientIPAddress = old.ClientIPAddress; diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index bf441e6076..77230a33d7 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -116,13 +116,7 @@ namespace OpenSim.Services.Interfaces public string ServerURI { get { return m_serverURI; } - set { - if ( value.EndsWith("/") ) { - m_serverURI = value; - } else { - m_serverURI = value + '/'; - } - } + set { m_serverURI = value; } } protected string m_serverURI; From fe8d3d5a2bc0ddbc051d8a7ad2412da5f3546075 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 22 Oct 2010 23:52:07 +0100 Subject: [PATCH 44/51] Revert "Merge remote branch 'otakup0pe/mantis5110'" This reverts commit 21187f459ea2ae590dda4249fa15ebf116d04fe0, reversing changes made to 8f34e46d7449be1c29419a232a8f7f1e5918f03c. --- OpenSim/Framework/Capabilities/CapsUtil.cs | 2 +- OpenSim/Framework/RegionInfo.cs | 39 +-------- .../Servers/HttpServer/BaseHttpServer.cs | 4 +- OpenSim/Region/Application/OpenSimBase.cs | 2 +- .../ClientStack/LindenUDP/LLUDPServer.cs | 2 +- .../InstantMessage/MessageTransferModule.cs | 6 +- .../EntityTransfer/EntityTransferModule.cs | 57 +++++++++---- .../EntityTransfer/HGEntityTransferModule.cs | 5 +- .../InterGrid/OpenGridProtocolModule.cs | 4 +- .../World/WorldMap/WorldMapModule.cs | 4 +- OpenSim/Region/Framework/Scenes/Scene.cs | 5 +- .../Region/Framework/Scenes/ScenePresence.cs | 4 +- .../Handlers/Hypergrid/HomeAgentHandlers.cs | 10 +-- .../Hypergrid/GatekeeperServiceConnector.cs | 50 +++++------- .../Hypergrid/UserAgentServiceConnector.cs | 2 - .../Connectors/Land/LandServiceConnector.cs | 3 +- .../Neighbour/NeighbourServiceConnector.cs | 2 +- .../SimianGrid/SimianGridServiceConnector.cs | 4 +- .../Simulation/SimulationServiceConnector.cs | 55 +++++++++++-- OpenSim/Services/GridService/GridService.cs | 2 +- .../Services/GridService/HypergridLinker.cs | 80 +++++-------------- .../HypergridService/GatekeeperService.cs | 2 +- .../HypergridService/UserAgentService.cs | 17 ++-- OpenSim/Services/Interfaces/IGridService.cs | 17 +--- .../LLLoginService/LLLoginResponse.cs | 29 ++++++- 25 files changed, 193 insertions(+), 214 deletions(-) diff --git a/OpenSim/Framework/Capabilities/CapsUtil.cs b/OpenSim/Framework/Capabilities/CapsUtil.cs index faf2708541..0334e4b4a2 100644 --- a/OpenSim/Framework/Capabilities/CapsUtil.cs +++ b/OpenSim/Framework/Capabilities/CapsUtil.cs @@ -41,7 +41,7 @@ namespace OpenSim.Framework.Capabilities /// public static string GetCapsSeedPath(string capsObjectPath) { - return "CAPS/" + capsObjectPath + "0000/"; + return "/CAPS/" + capsObjectPath + "0000/"; } /// diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 73b8bd0120..08d5398a18 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -115,20 +115,8 @@ namespace OpenSim.Framework /// public string ServerURI { - get { - if ( m_serverURI != string.Empty ) { - return m_serverURI; - } else { - return "http://" + m_externalHostName + ":" + m_httpPort + "/"; - } - } - set { - if ( value.EndsWith("/") ) { - m_serverURI = value; - } else { - m_serverURI = value + '/'; - } - } + get { return m_serverURI; } + set { m_serverURI = value; } } protected string m_serverURI; @@ -153,7 +141,6 @@ namespace OpenSim.Framework public SimpleRegionInfo() { - m_serverURI = string.Empty; } public SimpleRegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) @@ -163,7 +150,6 @@ namespace OpenSim.Framework m_internalEndPoint = internalEndPoint; m_externalHostName = externalUri; - m_serverURI = string.Empty; } public SimpleRegionInfo(uint regionLocX, uint regionLocY, string externalUri, uint port) @@ -174,7 +160,6 @@ namespace OpenSim.Framework m_externalHostName = externalUri; m_internalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int) port); - m_serverURI = string.Empty; } public SimpleRegionInfo(RegionInfo ConvertFrom) @@ -464,7 +449,6 @@ namespace OpenSim.Framework configMember = new ConfigurationMember(xmlNode, description, loadConfigurationOptions, handleIncomingConfiguration, !skipConsoleConfig); configMember.performConfigurationRetrieve(); - m_serverURI = string.Empty; } public RegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) @@ -474,12 +458,10 @@ namespace OpenSim.Framework m_internalEndPoint = internalEndPoint; m_externalHostName = externalUri; - m_serverURI = string.Empty; } public RegionInfo() { - m_serverURI = string.Empty; } public EstateSettings EstateSettings @@ -569,23 +551,10 @@ namespace OpenSim.Framework /// /// A well-formed URI for the host region server (namely "http://" + ExternalHostName) /// - public string ServerURI { - get { - if ( m_serverURI != string.Empty ) { - return m_serverURI; - } else { - return "http://" + m_externalHostName + ":" + m_httpPort + "/"; - } - } - set { - if ( value.EndsWith("/") ) { - m_serverURI = value; - } else { - m_serverURI = value + '/'; - } - } + get { return m_serverURI; } + set { m_serverURI = value; } } public string RegionName diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 0c1e5e013b..ba8c1941a8 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -348,7 +348,7 @@ namespace OpenSim.Framework.Servers.HttpServer { try { - //m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); +// m_log.Debug("[BASE HTTP SERVER]: Handling request to " + request.RawUrl); Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); @@ -376,7 +376,7 @@ namespace OpenSim.Framework.Servers.HttpServer string path = request.RawUrl; string handlerKey = GetHandlerKey(request.HttpMethod, path); - //m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); +// m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); if (TryGetStreamHandler(handlerKey, out requestHandler)) { diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 904a50c799..74ad1685f9 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -327,8 +327,8 @@ namespace OpenSim //regionInfo.originRegionID = regionInfo.RegionID; // set initial ServerURI + regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.InternalEndPoint.Port; regionInfo.HttpPort = m_httpServerPort; - regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort.ToString() + "/"; regionInfo.osSecret = m_osSecret; diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 624814a746..cb298fdad0 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -631,7 +631,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP IClientAPI client; if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView)) { - m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); + //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); return; } diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index fdc48c6b69..918fa04143 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -599,7 +599,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage try { - XmlRpcResponse GridResp = GridReq.Send(reginfo.ServerURI, 3000); + XmlRpcResponse GridResp = GridReq.Send("http://" + reginfo.ExternalHostName + ":" + reginfo.HttpPort, 3000); Hashtable responseData = (Hashtable)GridResp.Value; @@ -621,8 +621,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } catch (WebException e) { - m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0}} the host didn't respond ({2})", - reginfo.ServerURI, e.Message); + m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to http://{0}:{1} the host didn't respond ({2})", + reginfo.ExternalHostName, reginfo.HttpPort, e.Message); } return false; diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 925af3f579..38fff1cab3 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -197,8 +197,8 @@ 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} {2}@{3}", - finalDestination.RegionLocX / Constants.RegionSize, finalDestination.RegionLocY / Constants.RegionSize, finalDestination.RegionID, finalDestination.ServerURI); + 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); // Check that these are not the same coordinates if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX && @@ -254,8 +254,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: Request Teleport to {0} ({1}) {2}/{3}", - reg.ServerURI, finalDestination.ServerURI, finalDestination.RegionName, position); + "[ENTITY TRANSFER MODULE]: Request Teleport to {0}:{1}:{2}/{3}", + reg.ExternalHostName, reg.HttpPort, finalDestination.RegionName, position); uint newRegionX = (uint)(reg.RegionHandle >> 40); uint newRegionY = (((uint)(reg.RegionHandle)) >> 8); @@ -327,21 +327,43 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // OK, it got this agent. Let's close some child agents sp.CloseChildAgents(newRegionX, newRegionY); - IClientIPEndpoint ipepClient; + if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY)) { //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); + #region IP Translation for NAT - // Uses ipepClient above + IClientIPEndpoint ipepClient; if (sp.ClientView.TryGet(out ipepClient)) { - endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); + 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 - capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); 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, @@ -360,7 +382,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer else { agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle); - capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + capsPath = "http://" + finalDestination.ExternalHostName + ":" + finalDestination.HttpPort + + "/CAPS/" + agentCircuit.CapsPath + "0000/"; } // Expect avatar crossing is a heavy-duty function at the destination. @@ -493,8 +516,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) { - agent.CallbackURI = region.ServerURI + "agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; - m_log.Debug("Set callback URL to " + agent.CallbackURI); + agent.CallbackURI = "http://" + region.ExternalHostName + ":" + region.HttpPort + + "/agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; } @@ -819,8 +842,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer cAgent.Position = pos; if (isFlying) cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; - cAgent.CallbackURI = m_scene.RegionInfo.ServerURI + - "agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; + cAgent.CallbackURI = "http://" + m_scene.RegionInfo.ExternalHostName + ":" + m_scene.RegionInfo.HttpPort + + "/agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) { @@ -845,7 +868,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer neighbourRegion.RegionHandle); return agent; } - string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); + // TODO Should construct this behind a method + string capsPath = + "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort + + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/"; m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); @@ -1164,7 +1190,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer y = y / Constants.RegionSize; m_log.Info("[ENTITY TRANSFER MODULE]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")"); - string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath); + string capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort + + "/CAPS/" + a.CapsPath + "0000/"; string reason = String.Empty; diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 9a275ae215..1ac7508c20 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -123,9 +123,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) { m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); - GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); - m_log.Debug("GetfinalDestination serveruri -> " + real_destination.ServerURI); - return real_destination; + return m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); } return region; } @@ -151,7 +149,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) { - m_log.Debug("CreateAgent " + reg.ServerURI + " " + finalDestination.ServerURI); reason = string.Empty; logout = false; int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, reg.RegionID); diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs index 2dd7767d76..fd0e879e05 100644 --- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs +++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs @@ -595,12 +595,12 @@ namespace OpenSim.Region.CoreModules.InterGrid // DEPRECATED responseMap["seed_capability"] = OSD.FromString( - regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + "/" + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); + regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); // REPLACEMENT responseMap["region_seed_capability"] = OSD.FromString( - regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + "/" + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); + regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath)); responseMap["rez_avatar"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); responseMap["rez_avatar/rez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath); diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index fdbbccfbab..a182eeae7d 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -147,7 +147,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString(); regionimage = regionimage.Replace("-", ""); - m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "/index.php?method=" + regionimage); + m_log.Info("[WORLD MAP]: JPEG Map location: http://" + m_scene.RegionInfo.ExternalEndPoint.Address.ToString() + ":" + m_scene.RegionInfo.HttpPort.ToString() + "/index.php?method=" + regionimage); MainServer.Instance.AddHTTPHandler(regionimage, OnHTTPGetMapImage); MainServer.Instance.AddLLSDHandler( @@ -579,7 +579,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (mreg != null) { - httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString(); + httpserver = "http://" + mreg.ExternalEndPoint.Address.ToString() + ":" + mreg.HttpPort + "/MAP/MapItems/" + regionhandle.ToString(); lock (m_cachedRegionMapItemsAddress) { if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ef18d02323..c9ae558cd2 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3738,12 +3738,9 @@ namespace OpenSim.Region.Framework.Scenes // We have to wait until the viewer contacts this region after receiving EAC. // That calls AddNewClient, which finally creates the ScenePresence - m_log.Debug("ICADU -> pre wait"); ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); - m_log.Debug("ICADU -> post wait"); if (childAgentUpdate != null) { - m_log.Debug("ICADU -> not child agent!"); childAgentUpdate.ChildAgentDataUpdate(cAgentData); return true; } @@ -3759,7 +3756,7 @@ namespace OpenSim.Region.Framework.Scenes /// true if we handled it. public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) { - m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); + //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); if (childAgentUpdate != null) { diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 68ac178e50..13d99643bf 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2925,7 +2925,7 @@ namespace OpenSim.Region.Framework.Scenes public void ChildAgentDataUpdate(AgentData cAgentData) { - m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); + //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); if (!IsChildAgent) return; @@ -2976,8 +2976,6 @@ namespace OpenSim.Region.Framework.Scenes public void CopyTo(AgentData cAgent) { - cAgent.CallbackURI = m_callbackURI; - cAgent.AgentID = UUID; cAgent.RegionID = Scene.RegionInfo.RegionID; diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs index a5ec4f2b08..f64a07973e 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs @@ -124,8 +124,6 @@ namespace OpenSim.Server.Handlers.Hypergrid UUID uuid = UUID.Zero; string regionname = string.Empty; string gatekeeper_host = string.Empty; - string gatekeeper_serveruri = string.Empty; - string destination_serveruri = string.Empty; int gatekeeper_port = 0; IPEndPoint client_ipaddress = null; @@ -133,13 +131,8 @@ namespace OpenSim.Server.Handlers.Hypergrid gatekeeper_host = args["gatekeeper_host"].AsString(); if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null) Int32.TryParse(args["gatekeeper_port"].AsString(), out gatekeeper_port); - if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] !=null) - gatekeeper_serveruri = args["gatekeeper_serveruri"]; - if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] !=null) - destination_serveruri = args["destination_serveruri"]; GridRegion gatekeeper = new GridRegion(); - gatekeeper.ServerURI = gatekeeper_serveruri; gatekeeper.ExternalHostName = gatekeeper_host; gatekeeper.HttpPort = (uint)gatekeeper_port; gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); @@ -180,8 +173,7 @@ namespace OpenSim.Server.Handlers.Hypergrid destination.RegionLocX = x; destination.RegionLocY = y; destination.RegionName = regionname; - destination.ServerURI = destination_serveruri; - + AgentCircuitData aCircuit = new AgentCircuitData(); try { diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 70bafda233..479a80e297 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -63,12 +63,12 @@ namespace OpenSim.Services.Connectors.Hypergrid protected override string AgentPath() { - return "foreignagent/"; + return "/foreignagent/"; } protected override string ObjectPath() { - return "foreignobject/"; + return "/foreignobject/"; } public bool LinkRegion(GridRegion info, out UUID regionID, out ulong realHandle, out string externalName, out string imageURL, out string reason) @@ -86,11 +86,12 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("link_region", paramList); - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Linking to " + info.ServerURI); + string uri = "http://" + ((info.ServerURI != null && info.ServerURI != string.Empty && !info.ServerURI.StartsWith("http:")) ? info.ServerURI : info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Linking to " + uri); XmlRpcResponse response = null; try { - response = request.Send(info.ServerURI, 10000); + response = request.Send(uri, 10000); } catch (Exception e) { @@ -107,8 +108,8 @@ namespace OpenSim.Services.Connectors.Hypergrid } hash = (Hashtable)response.Value; - foreach (Object o in hash) - m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); try { bool success = false; @@ -116,20 +117,16 @@ namespace OpenSim.Services.Connectors.Hypergrid if (success) { UUID.TryParse((string)hash["uuid"], out regionID); - m_log.Debug(">> HERE, uuid: " + regionID); + //m_log.Debug(">> HERE, uuid: " + uuid); if ((string)hash["handle"] != null) { realHandle = Convert.ToUInt64((string)hash["handle"]); - m_log.Debug(">> HERE, realHandle: " + realHandle); + //m_log.Debug(">> HERE, realHandle: " + realHandle); } - if (hash["region_image"] != null) { + if (hash["region_image"] != null) imageURL = (string)hash["region_image"]; - m_log.Debug(">> HERE, imageURL: " + imageURL); - } - if (hash["external_name"] != null) { + if (hash["external_name"] != null) externalName = (string)hash["external_name"]; - m_log.Debug(">> HERE, externalName: " + externalName); - } } } @@ -191,11 +188,12 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_region", paramList); - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI); + string uri = "http://" + ((gatekeeper.ServerURI != null && gatekeeper.ServerURI != string.Empty && !gatekeeper.ServerURI.StartsWith("http:")) ? gatekeeper.ServerURI : gatekeeper.ExternalEndPoint.Address + ":" + gatekeeper.HttpPort + "/"); + m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + uri); XmlRpcResponse response = null; try { - response = request.Send(gatekeeper.ServerURI, 10000); + response = request.Send(uri, 10000); } catch (Exception e) { @@ -221,48 +219,38 @@ namespace OpenSim.Services.Connectors.Hypergrid GridRegion region = new GridRegion(); UUID.TryParse((string)hash["uuid"], out region.RegionID); - m_log.Debug(">> HERE, uuid: " + 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); + //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); + //m_log.Debug(">> HERE, y: " + region.RegionLocY); } if (hash["region_name"] != null) { region.RegionName = (string)hash["region_name"]; - m_log.Debug(">> HERE, region_name: " + region.RegionName); + //m_log.Debug(">> HERE, name: " + region.RegionName); } - if (hash["hostname"] != null) { + if (hash["hostname"] != null) region.ExternalHostName = (string)hash["hostname"]; - m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); - } if (hash["http_port"] != null) { uint p = 0; UInt32.TryParse((string)hash["http_port"], out p); region.HttpPort = p; - m_log.Debug(">> HERE, http_port: " + region.HttpPort); } 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); - m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); - } - - if (hash["server_uri"] != null) - { - region.ServerURI = (string) hash["server_uri"]; - m_log.Debug(">> HERE, server_uri: " + region.ServerURI); } // Successful return diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 0c41935215..247dd7ed10 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -232,14 +232,12 @@ namespace OpenSim.Services.Connectors.Hypergrid m_log.Debug("[USER AGENT CONNECTOR]: PackAgentCircuitData failed with exception: " + e.Message); } // Add the input arguments - args["gatekeeper_serveruri"] = OSD.FromString(gatekeeper.ServerURI); args["gatekeeper_host"] = OSD.FromString(gatekeeper.ExternalHostName); args["gatekeeper_port"] = OSD.FromString(gatekeeper.HttpPort.ToString()); args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); args["destination_name"] = OSD.FromString(destination.RegionName); args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); - args["destination_serveruri"] = OSD.FromString(destination.ServerURI); // 10/3/2010 // I added the client_ip up to the regular AgentCircuitData, so this doesn't need to be here. diff --git a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs index 4b25ac819a..8143b5a89f 100644 --- a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs +++ b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs @@ -84,7 +84,8 @@ namespace OpenSim.Services.Connectors if (info != null) // just to be sure { XmlRpcRequest request = new XmlRpcRequest("land_data", paramList); - XmlRpcResponse response = request.Send(info.ServerURI, 10000); + string uri = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"; + XmlRpcResponse response = request.Send(uri, 10000); if (response.IsFault) { m_log.ErrorFormat("[LAND CONNECTOR]: remote call returned an error: {0}", response.FaultString); diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs index 9c57a40701..0a982f8d57 100644 --- a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs +++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs @@ -87,7 +87,7 @@ namespace OpenSim.Services.Connectors public bool DoHelloNeighbourCall(GridRegion region, RegionInfo thisRegion) { - string uri = region.ServerURI + "/region/" + thisRegion.RegionID + "/"; + string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/region/" + thisRegion.RegionID + "/"; //m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri); WebRequest HelloNeighbourRequest = WebRequest.Create(uri); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index 8076fab589..168b233893 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -145,6 +145,8 @@ namespace OpenSim.Services.Connectors.SimianGrid Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0); + string httpAddress = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort + "/"; + OSDMap extraData = new OSDMap { { "ServerURI", OSD.FromString(regionInfo.ServerURI) }, @@ -166,7 +168,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Name", regionInfo.RegionName }, { "MinPosition", minPosition.ToString() }, { "MaxPosition", maxPosition.ToString() }, - { "Address", regionInfo.ServerURI }, + { "Address", httpAddress }, { "Enabled", "1" }, { "ExtraData", OSDParser.SerializeJsonString(extraData) } }; diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index c4284eb920..a5f748f0c4 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -72,7 +72,7 @@ namespace OpenSim.Services.Connectors.Simulation protected virtual string AgentPath() { - return "agent/"; + return "/agent/"; } public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) @@ -104,7 +104,26 @@ namespace OpenSim.Services.Connectors.Simulation return false; } - string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; + string uri = string.Empty; + + // HACK -- Simian grid make it work!!! + if (destination.ServerURI != null && destination.ServerURI != string.Empty && !destination.ServerURI.StartsWith("http:")) + uri = "http://" + destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; + else + { + try + { + uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + aCircuit.AgentID + "/"; + } + catch (Exception e) + { + m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent create. Reason: " + e.Message); + reason = e.Message; + return false; + } + } + + //Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri); AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri); AgentCreateRequest.Method = "POST"; @@ -258,7 +277,17 @@ namespace OpenSim.Services.Connectors.Simulation private bool UpdateAgent(GridRegion destination, IAgentData cAgentData) { // Eventually, we want to use a caps url instead of the agentID - string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; + string uri = string.Empty; + try + { + uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + cAgentData.AgentID + "/"; + } + catch (Exception e) + { + m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent update. Reason: " + e.Message); + return false; + } + //Console.WriteLine(" >>> DoAgentUpdateCall <<< " + uri); HttpWebRequest ChildUpdateRequest = (HttpWebRequest)WebRequest.Create(uri); ChildUpdateRequest.Method = "PUT"; @@ -356,7 +385,8 @@ namespace OpenSim.Services.Connectors.Simulation { agent = null; // Eventually, we want to use a caps url instead of the agentID - string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + string uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + //Console.WriteLine(" >>> DoRetrieveRootAgentCall <<< " + uri); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.Method = "GET"; @@ -377,6 +407,7 @@ namespace OpenSim.Services.Connectors.Simulation sr = new StreamReader(webResponse.GetResponseStream()); reply = sr.ReadToEnd().Trim(); + //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: ChilAgentUpdate reply was " + reply); } catch (WebException ex) @@ -397,6 +428,7 @@ namespace OpenSim.Services.Connectors.Simulation OSDMap args = Util.GetOSDMap(reply); if (args == null) { + //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: Error getting OSDMap from reply"); return false; } @@ -405,6 +437,7 @@ namespace OpenSim.Services.Connectors.Simulation return true; } + //Console.WriteLine("[REMOTE SIMULATION CONNECTOR]: DoRetrieveRootAgentCall returned status " + webResponse.StatusCode); return false; } @@ -446,8 +479,18 @@ namespace OpenSim.Services.Connectors.Simulation public bool CloseAgent(GridRegion destination, UUID id) { - string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + string uri = string.Empty; + try + { + uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + } + catch (Exception e) + { + m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Unable to resolve external endpoint on agent close. Reason: " + e.Message); + return false; + } + //Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri); WebRequest request = WebRequest.Create(uri); request.Method = "DELETE"; @@ -495,7 +538,7 @@ namespace OpenSim.Services.Connectors.Simulation public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall) { string uri - = destination.ServerURI + ObjectPath() + sog.UUID + "/"; + = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + ObjectPath() + sog.UUID + "/"; //m_log.Debug(" >>> DoCreateObjectCall <<< " + uri); WebRequest ObjectCreateRequest = WebRequest.Create(uri); diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index 125c2be8cf..e7988d6e93 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -479,7 +479,7 @@ namespace OpenSim.Services.GridService OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); MainConsole.Instance.Output(String.Format("{0,-20} {1}\n{2,-20} {3}\n{4,-39} {5}\n\n", r.RegionName, r.RegionID, - String.Format("{0},{1}", r.posX, r.posY), r.Data["serverURI"], + String.Format("{0},{1}", r.posX, r.posY), "http://" + r.Data["serverIP"].ToString() + ":" + r.Data["serverPort"].ToString(), r.Data["owner_uuid"].ToString(), flags.ToString())); } return; diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index c273d21229..b86fb6f01c 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -126,12 +126,11 @@ namespace OpenSim.Services.GridService if (MainConsole.Instance != null) { - MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region", "link-region []", "Link a HyperGrid Region", RunCommand); - MainConsole.Instance.Commands.AddCommand("hypergrid", false, "legacy-link-region", - "legacy-link-region []", - "Link a hypergrid region (deprecated)", RunCommand); + MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region", + "link-region :[:] ", + "Link a hypergrid region", RunCommand); MainConsole.Instance.Commands.AddCommand("hypergrid", false, "unlink-region", - "unlink-region ", + "unlink-region or : ", "Unlink a hypergrid region", RunCommand); MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-mapping", "link-mapping [ ] ", "Set local coordinate to map HG regions to", RunCommand); @@ -199,33 +198,28 @@ namespace OpenSim.Services.GridService return null; } - - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) - { - return TryCreateLink(scopeID, xloc, yloc, externalRegionName, externalPort, externalHostName, null, out regInfo, out reason); - } - - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string externalRegionName, uint externalPort, string externalHostName, string serverURI, out GridRegion regInfo, out string reason) + + + // From the command line and the 2 above + public bool TryCreateLink(UUID scopeID, int xloc, int yloc, + string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason) { m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0}:{1}:{2}, in {3}-{4}", externalHostName, externalPort, externalRegionName, xloc, yloc); reason = string.Empty; regInfo = new GridRegion(); - if ( externalPort > 0) - regInfo.HttpPort = externalPort; - else - regInfo.HttpPort = 0; - if ( externalHostName != null) - regInfo.ExternalHostName = externalHostName; - else - regInfo.ExternalHostName = "0.0.0.0"; - if ( serverURI != null) - regInfo.ServerURI = serverURI; - + regInfo.RegionName = externalRegionName; + regInfo.HttpPort = externalPort; + regInfo.ExternalHostName = externalHostName; regInfo.RegionLocX = xloc; regInfo.RegionLocY = yloc; regInfo.ScopeID = scopeID; + // Big HACK for Simian Grid !!! + // We need to clean up all URLs used in OpenSim !!! + if (externalHostName.Contains("/")) + regInfo.ServerURI = externalHostName; + try { regInfo.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int)0); @@ -256,14 +250,9 @@ namespace OpenSim.Services.GridService } regInfo.RegionID = regionID; + if (regInfo.RegionName == string.Empty) + regInfo.RegionName = regInfo.ExternalHostName; - if ( externalName == string.Empty ) - regInfo.RegionName = regInfo.ServerURI; - else - regInfo.RegionName = externalName; - - m_log.Debug("naming linked region " + regInfo.RegionName); - // Try get the map image //regInfo.TerrainImage = m_GatekeeperConnector.GetMapImage(regionID, imageURL); // I need a texture that works for this... the one I tried doesn't seem to be working @@ -445,21 +434,6 @@ namespace OpenSim.Services.GridService RunHGCommand(command, cmdparams); } - - private void RunLinkRegionCommand(string[] cmdparams) - { - int xloc, yloc; - string serverURI; - string remoteName = null; - xloc = Convert.ToInt32(cmdparams[0]) * (int)Constants.RegionSize; - yloc = Convert.ToInt32(cmdparams[1]) * (int)Constants.RegionSize; - serverURI = cmdparams[2]; - if (cmdparams.Length == 4) - remoteName = cmdparams[3]; - string reason = string.Empty; - GridRegion regInfo; - TryCreateLink(UUID.Zero, xloc, yloc, remoteName, 0, null, serverURI, out regInfo, out reason); - } private void RunHGCommand(string command, string[] cmdparams) { @@ -482,18 +456,6 @@ namespace OpenSim.Services.GridService } } else if (command.Equals("link-region")) - { - if (cmdparams.Length > 0 && cmdparams.Length < 5) - { - RunLinkRegionCommand(cmdparams); - } - else - { - LinkRegionCmdUsage(); - } - return; - } - else if (command.Equals("legacy-link-region")) { if (cmdparams.Length < 3) { @@ -547,16 +509,12 @@ namespace OpenSim.Services.GridService int xloc, yloc; uint externalPort; string externalHostName; - string serverURI; try { xloc = Convert.ToInt32(cmdparams[0]); yloc = Convert.ToInt32(cmdparams[1]); externalPort = Convert.ToUInt32(cmdparams[3]); externalHostName = cmdparams[2]; - if ( cmdparams.Length == 4 ) { - - } //internalPort = Convert.ToUInt32(cmdparams[4]); //remotingPort = Convert.ToUInt32(cmdparams[5]); } diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs index 9e961636ce..3f5c4f1400 100644 --- a/OpenSim/Services/HypergridService/GatekeeperService.cs +++ b/OpenSim/Services/HypergridService/GatekeeperService.cs @@ -157,7 +157,7 @@ namespace OpenSim.Services.HypergridService string regionimage = "regionImage" + region.RegionID.ToString(); regionimage = regionimage.Replace("-", ""); - imageURL = region.ServerURI + "index.php?method=" + regionimage; + imageURL = "http://" + region.ExternalHostName + ":" + region.HttpPort + "/index.php?method=" + regionimage; return true; } diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index eb19fe2fdc..eb6433cc6f 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -134,28 +134,23 @@ namespace OpenSim.Services.HypergridService public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason) { m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", - agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); + agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), + gatekeeper.ExternalHostName +":"+ gatekeeper.HttpPort); - m_log.Debug("LATG final server uri -> " + finalDestination.ServerURI ); // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination GridRegion region = new GridRegion(gatekeeper); - region.ServerURI = gatekeeper.ServerURI; - region.ExternalHostName = finalDestination.ExternalHostName; - region.InternalEndPoint = finalDestination.InternalEndPoint; region.RegionName = finalDestination.RegionName; region.RegionID = finalDestination.RegionID; region.RegionLocX = finalDestination.RegionLocX; region.RegionLocY = finalDestination.RegionLocY; // Generate a new service session - agentCircuit.ServiceSessionID = region.ServerURI + ";" + UUID.Random(); + agentCircuit.ServiceSessionID = "http://" + region.ExternalHostName + ":" + region.HttpPort + ";" + UUID.Random(); TravelingAgentInfo old = UpdateTravelInfo(agentCircuit, region); - m_log.Debug("region ServerURI -> " + region.ServerURI); - bool success = false; string myExternalIP = string.Empty; - string gridName = gatekeeper.ServerURI; + string gridName = "http://" + gatekeeper.ExternalHostName + ":" + gatekeeper.HttpPort; if (m_GridName == gridName) success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); else @@ -164,7 +159,7 @@ namespace OpenSim.Services.HypergridService if (!success) { m_log.DebugFormat("[USER AGENT SERVICE]: Unable to login user {0} {1} to grid {2}, reason: {3}", - agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason); + agentCircuit.firstname, agentCircuit.lastname, region.ExternalHostName + ":" + region.HttpPort, reason); // restore the old travel info lock (m_TravelingAgents) @@ -215,7 +210,7 @@ namespace OpenSim.Services.HypergridService m_TravelingAgents[agentCircuit.SessionID] = travel; } travel.UserID = agentCircuit.AgentID; - travel.GridExternalName = region.ServerURI; + travel.GridExternalName = "http://" + region.ExternalHostName + ":" + region.HttpPort; travel.ServiceToken = agentCircuit.ServiceSessionID; if (old != null) travel.ClientIPAddress = old.ClientIPAddress; diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index 6d3bff7683..77230a33d7 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -115,20 +115,8 @@ namespace OpenSim.Services.Interfaces /// public string ServerURI { - get { - if ( m_serverURI != string.Empty ) { - return m_serverURI; - } else { - return "http://" + m_externalHostName + ":" + m_httpPort + "/"; - } - } - set { - if ( value.EndsWith("/") ) { - m_serverURI = value; - } else { - m_serverURI = value + '/'; - } - } + get { return m_serverURI; } + set { m_serverURI = value; } } protected string m_serverURI; @@ -176,7 +164,6 @@ namespace OpenSim.Services.Interfaces public GridRegion() { - m_serverURI = string.Empty; } public GridRegion(int regionLocX, int regionLocY, IPEndPoint internalEndPoint, string externalUri) diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index f985ab21ba..0da1715849 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -333,7 +333,34 @@ namespace OpenSim.Services.LLLoginService private void FillOutSeedCap(AgentCircuitData aCircuit, GridRegion destination, IPEndPoint ipepClient) { - SeedCapability = destination.ServerURI + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); + string capsSeedPath = String.Empty; + + // Don't use the following! It Fails for logging into any region not on the same port as the http server! + // Kept here so it doesn't happen again! + // response.SeedCapability = regionInfo.ServerURI + capsSeedPath; + + #region IP Translation for NAT + if (ipepClient != null) + { + capsSeedPath + = "http://" + + NetworkUtil.GetHostFor(ipepClient.Address, destination.ExternalHostName) + + ":" + + destination.HttpPort + + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); + } + else + { + capsSeedPath + = "http://" + + destination.ExternalHostName + + ":" + + destination.HttpPort + + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath); + } + #endregion + + SeedCapability = capsSeedPath; } private void SetDefaultValues() From 627d1a42fe11937a1c35659ca0fad6f89754f654 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 23 Oct 2010 20:39:41 -0700 Subject: [PATCH 45/51] Added inner exception handling in Shape deserialization processing, so that the whole Shape processing returns a valid Shape object. --- .../Serialization/SceneObjectSerializer.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 044b5991d2..95908fc274 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -1426,7 +1426,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization reader.ReadStartElement(name); vec.X = reader.ReadElementContentAsFloat(reader.Name, String.Empty); // X or x - vec.Y = reader.ReadElementContentAsFloat(reader.Name, String.Empty); // Y or Y + vec.Y = reader.ReadElementContentAsFloat(reader.Name, String.Empty); // Y or y vec.Z = reader.ReadElementContentAsFloat(reader.Name, String.Empty); // Z or z reader.ReadEndElement(); @@ -1501,15 +1501,28 @@ namespace OpenSim.Region.Framework.Scenes.Serialization reader.ReadStartElement(name, String.Empty); // Shape + string nodeName = string.Empty; while (reader.NodeType != XmlNodeType.EndElement) { + nodeName = reader.Name; //m_log.DebugFormat("[XXX] Processing: {0}", reader.Name); ShapeXmlProcessor p = null; if (m_ShapeXmlProcessors.TryGetValue(reader.Name, out p)) - p(shape, reader); + { + try + { + p(shape, reader); + } + catch (Exception e) + { + m_log.DebugFormat("[SceneObjectSerializer]: exception while parsing Shape {0}: {1}", nodeName, e); + if (reader.NodeType == XmlNodeType.EndElement) + reader.Read(); + } + } else { -// m_log.DebugFormat("[SceneObjectSerializer]: caught unknown element in Shape {0}", reader.Name); + // m_log.DebugFormat("[SceneObjectSerializer]: caught unknown element in Shape {0}", reader.Name); reader.ReadOuterXml(); } } From 852c61aaa6e5a2e41e7c1724ee974382a55007ec Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 24 Oct 2010 18:19:48 +0200 Subject: [PATCH 46/51] Add PRIM_NAME, PRIM_DESC and PRIM_ROT_LOCAL --- .../Shared/Api/Implementation/LSL_Api.cs | 27 +++++++++++++++++++ .../Shared/Api/Runtime/LSL_Constants.cs | 3 +++ 2 files changed, 30 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 59a36187cf..1a13deae5a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7267,6 +7267,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api Util.Clip((float)primTextColor.z, 0.0f, 1.0f)); part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); + break; + case (int)ScriptBaseClass.PRIM_NAME: + if (remain < 1) + return; + string primName = rules.GetLSLStringItem(idx++); + part.Name = primName; + break; + case (int)ScriptBaseClass.PRIM_DESC: + if (remain < 1) + return; + string primDesc = rules.GetLSLStringItem(idx++); + part.Description = primDesc; + break; + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + if (remain < 1) + return; + LSL_Rotation lr = rules.GetQuaternionItem(idx++); + SetRot(part, Rot2Quaternion(lr)); break; } } @@ -7813,6 +7831,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api textColor.B)); res.Add(new LSL_Float(textColor.A)); break; + case (int)ScriptBaseClass.PRIM_NAME: + res.Add(part.Name); + break; + case (int)ScriptBaseClass.PRIM_DESC: + res.Add(part.Description); + break; + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); + break; } } return res; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 5da6bb9a21..b96e977539 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -316,6 +316,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int PRIM_POINT_LIGHT = 23; // Huh? public const int PRIM_GLOW = 25; public const int PRIM_TEXT = 26; + public const int PRIM_NAME = 27; + public const int PRIM_DESC = 28; + public const int PRIM_ROT_LOCAL = 29; public const int PRIM_TEXGEN_DEFAULT = 0; public const int PRIM_TEXGEN_PLANAR = 1; From c74c1620a15fcf032a074ed2b979a06f2913e08b Mon Sep 17 00:00:00 2001 From: Latif Khalifa Date: Sun, 24 Oct 2010 22:47:53 +0200 Subject: [PATCH 47/51] * Updated libomv to r3461 Main reason for upgrade is to revert API change that was introduced in order to support headerless binary LLSD decoding needed for deserialization of the mesh assets, which turned out to be unnecessary as we can transparently decode both kinds. --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 4 ++-- bin/OpenMetaverse.Rendering.Meshmerizer.dll | Bin 20480 -> 20480 bytes bin/OpenMetaverse.StructuredData.XML | 12 ++++++------ bin/OpenMetaverse.StructuredData.dll | Bin 102400 -> 102400 bytes bin/OpenMetaverse.XML | 9 +++++---- bin/OpenMetaverse.dll | Bin 1716224 -> 1716224 bytes bin/OpenMetaverseTypes.dll | Bin 114688 -> 114688 bytes 7 files changed, 13 insertions(+), 12 deletions(-) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 1257804cfa..d770ad1aa7 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -287,7 +287,7 @@ namespace OpenSim.Region.Physics.Meshing long start = 0; using (MemoryStream data = new MemoryStream(primShape.SculptData)) { - meshOsd = (OSDMap)OSDParser.DeserializeLLSDBinary(data, true); + meshOsd = (OSDMap)OSDParser.DeserializeLLSDBinary(data); start = data.Position; } @@ -324,7 +324,7 @@ namespace OpenSim.Region.Physics.Meshing byte[] decompressedBuf = outMs.GetBuffer(); - decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf, true); + decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf); } } } diff --git a/bin/OpenMetaverse.Rendering.Meshmerizer.dll b/bin/OpenMetaverse.Rendering.Meshmerizer.dll index 0160d21188aee99ab19a5c487e52c59c3f3916c0..f89ac5a5950c580299df4193487ec869eaaeedad 100755 GIT binary patch delta 46 zcmV+}0MY+|paFoO0g#9Te3- - + Deserializes binary LLSD - - + Serialized data + OSD containting deserialized data - + Deserializes binary LLSD - - + Stream to read the data from + OSD containting deserialized data diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll index c1e54faf656fe7a8c537e4f1e504e366ef98c2f8..33b19caea064b5f777238e15d53245f96751277b 100644 GIT binary patch delta 28477 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 MEdLeNQX2OE04$yGmH+?% diff --git a/bin/OpenMetaverse.XML b/bin/OpenMetaverse.XML index 56f0c87dcf..f5bda4b4b9 100644 --- a/bin/OpenMetaverse.XML +++ b/bin/OpenMetaverse.XML @@ -10318,12 +10318,13 @@ target avatars to lure custom message to send with invitation - + Respond to a teleport lure by either accepting it and initiating the teleport, or denying it of the avatar sending the lure + IM session of the incoming lure request true to accept the lure, false to decline it @@ -19866,9 +19867,6 @@ Total number of wearables per bake layer - - Total number of textures on an avatar, baked or not - Mapping between BakeType and AvatarTextureIndex @@ -20315,6 +20313,9 @@ Tint that should be applied to the texture + + Where on avatar does this texture belong + Contains the Event data returned from the data server from an AgentWearablesRequest diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll index a07d64f00869da184487e3a78458528d30ca9936..f5952b45a2f90e25dcccfdf7000965065f3a0a35 100644 GIT binary patch delta 244776 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 O^~UwStD4--{r>@3YsQlR diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll index 2d7a372e5144cf13325e20a595ab5b8891b5e9a1..f4f701bac4378ebfec8501e7eded8476394bdb15 100644 GIT binary patch delta 85 zcmV-b0IL6hfCqqp2at#Zb(q9~i?xdZFJ>e)Lq$SDFf=kPF*7qXEi^VTF)cYVGe#{q rML|R}L`FqKHaRf2-ev)Q5)eYL>s&Mw0Y;KPj;%fZ){wVsc>$D0it8M7 delta 85 zcmZo@U~gz(pU}ZE Date: Wed, 27 Oct 2010 00:01:03 -0400 Subject: [PATCH 48/51] Formatting cleanup. --- .../CoreModules/Avatar/Chat/ChatModule.cs | 2 +- .../Archiver/InventoryArchiveReadRequest.cs | 8 +-- .../Archiver/InventoryArchiveWriteRequest.cs | 4 +- .../ArchiveWriteRequestPreparation.cs | 6 +- .../Region/CoreModules/World/Sun/SunModule.cs | 57 ++++++------------- .../Region/Framework/Scenes/EventManager.cs | 6 +- .../Serialization/SceneObjectSerializer.cs | 2 +- .../XmlRpcGroups/GroupsMessagingModule.cs | 4 +- .../Scripting/Minimodule/MRMModule.cs | 11 ++-- 9 files changed, 37 insertions(+), 63 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index d76ff47f87..4359c01d5d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -238,7 +238,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat } (scene as Scene).EventManager.TriggerOnChatToClients( - fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); + fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); } static private Vector3 CenterOfRegion = new Vector3(128, 128, 30); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 55005572ba..046b05f48e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -143,7 +143,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { LoadControlFile(filePath, data); - } + } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) { if (LoadAsset(filePath, data)) @@ -479,11 +479,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// protected void LoadControlFile(string path, byte[] data) - { + { XDocument doc = XDocument.Parse(Encoding.ASCII.GetString(data)); XElement archiveElement = doc.Element("archive"); int majorVersion = int.Parse(archiveElement.Attribute("major_version").Value); - int minorVersion = int.Parse(archiveElement.Attribute("minor_version").Value); + int minorVersion = int.Parse(archiveElement.Attribute("minor_version").Value); string version = string.Format("{0}.{1}", majorVersion, minorVersion); if (majorVersion > MAX_MAJOR_VERSION) @@ -492,7 +492,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver string.Format( "The IAR you are trying to load has major version number of {0} but this version of OpenSim can only load IARs with major version number {1} and below", majorVersion, MAX_MAJOR_VERSION)); - } + } m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index 249a8b4b9c..9080e1c92f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -213,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver public void Execute() { try - { + { InventoryFolderBase inventoryFolder = null; InventoryItemBase inventoryItem = null; InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); @@ -277,7 +277,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // Write out control file. This has to be done first so that subsequent loaders will see this file first // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p1ControlFile()); - m_log.InfoFormat("[INVENTORY ARCHIVER]: Added control file to archive."); + m_log.InfoFormat("[INVENTORY ARCHIVER]: Added control file to archive."); if (inventoryFolder != null) { diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 1687d06350..31820794b8 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -199,13 +199,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver { majorVersion = 1; minorVersion = 0; - } + } */ m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); // if (majorVersion == 1) // { -// m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); +// m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); // } @@ -232,6 +232,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver sw.Close(); return s; - } + } } } diff --git a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs index a6dc2ec79a..cea7c78ce8 100644 --- a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs +++ b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs @@ -44,10 +44,8 @@ namespace OpenSim.Region.CoreModules /// it is not based on ~06:00 == Sun Rise. Rather it is based on 00:00 being sun-rise. /// - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - // // Global Constants used to determine where in the sky the sun is // @@ -108,26 +106,25 @@ namespace OpenSim.Region.CoreModules private Scene m_scene = null; // Calculated Once in the lifetime of a region - private long TicksToEpoch; // Elapsed time for 1/1/1970 - private uint SecondsPerSunCycle; // Length of a virtual day in RW seconds - private uint SecondsPerYear; // Length of a virtual year in RW seconds - private double SunSpeed; // Rate of passage in radians/second - private double SeasonSpeed; // Rate of change for seasonal effects - // private double HoursToRadians; // Rate of change for seasonal effects - private long TicksUTCOffset = 0; // seconds offset from UTC + private long TicksToEpoch; // Elapsed time for 1/1/1970 + private uint SecondsPerSunCycle; // Length of a virtual day in RW seconds + private uint SecondsPerYear; // Length of a virtual year in RW seconds + private double SunSpeed; // Rate of passage in radians/second + private double SeasonSpeed; // Rate of change for seasonal effects + // private double HoursToRadians; // Rate of change for seasonal effects + private long TicksUTCOffset = 0; // seconds offset from UTC // Calculated every update - private float OrbitalPosition; // Orbital placement at a point in time - private double HorizonShift; // Axis offset to skew day and night - private double TotalDistanceTravelled; // Distance since beginning of time (in radians) - private double SeasonalOffset; // Seaonal variation of tilt - private float Magnitude; // Normal tilt - // private double VWTimeRatio; // VW time as a ratio of real time + private float OrbitalPosition; // Orbital placement at a point in time + private double HorizonShift; // Axis offset to skew day and night + private double TotalDistanceTravelled; // Distance since beginning of time (in radians) + private double SeasonalOffset; // Seaonal variation of tilt + private float Magnitude; // Normal tilt + // private double VWTimeRatio; // VW time as a ratio of real time // Working values private Vector3 Position = Vector3.Zero; private Vector3 Velocity = Vector3.Zero; - private Quaternion Tilt = new Quaternion(1.0f, 0.0f, 0.0f, 0.0f); - + private Quaternion Tilt = new Quaternion(1.0f, 0.0f, 0.0f, 0.0f); // Used to fix the sun in the sky so it doesn't move based on current time private bool m_SunFixed = false; @@ -135,8 +132,6 @@ namespace OpenSim.Region.CoreModules private const int TICKS_PER_SECOND = 10000000; - - // Current time in elapsed seconds since Jan 1st 1970 private ulong CurrentTime { @@ -149,8 +144,6 @@ namespace OpenSim.Region.CoreModules // Time in seconds since UTC to use to calculate sun position. ulong PosTime = 0; - - /// /// Calculate the sun's orbital position and its velocity. /// @@ -202,7 +195,6 @@ namespace OpenSim.Region.CoreModules PosTime += (ulong)(((CurDayPercentage - 0.5) / .5) * NightSeconds); } } - } TotalDistanceTravelled = SunSpeed * PosTime; // distance measured in radians @@ -251,7 +243,6 @@ namespace OpenSim.Region.CoreModules Velocity.X = 0; Velocity.Y = 0; Velocity.Z = 0; - } else { @@ -271,9 +262,7 @@ namespace OpenSim.Region.CoreModules private float GetCurrentTimeAsLindenSunHour() { if (m_SunFixed) - { return m_SunFixedHour + 6; - } return GetCurrentSunHour() + 6.0f; } @@ -297,8 +286,6 @@ namespace OpenSim.Region.CoreModules m_scene.AddCommand(this, String.Format("sun {0}", kvp.Key), String.Format("{0} - {1}", kvp.Key, kvp.Value), "", HandleSunConsoleCommand); } - - TimeZone local = TimeZone.CurrentTimeZone; TicksUTCOffset = local.GetUtcOffset(local.ToLocalTime(DateTime.Now)).Ticks; m_log.Debug("[SUN]: localtime offset is " + TicksUTCOffset); @@ -325,13 +312,11 @@ namespace OpenSim.Region.CoreModules // must hard code to ~.5 to match sun position in LL based viewers m_HorizonShift = config.Configs["Sun"].GetDouble("day_night_offset", d_day_night); - // Scales the sun hours 0...12 vs 12...24, essentially makes daylight hours longer/shorter vs nighttime hours m_DayTimeSunHourScale = config.Configs["Sun"].GetDouble("day_time_sun_hour_scale", d_DayTimeSunHourScale); // Update frequency in frames m_UpdateInterval = config.Configs["Sun"].GetInt("update_interval", d_frame_mod); - } catch (Exception e) { @@ -391,10 +376,8 @@ namespace OpenSim.Region.CoreModules } scene.RegisterModuleInterface(this); - } - public void PostInitialise() { } @@ -402,7 +385,7 @@ namespace OpenSim.Region.CoreModules public void Close() { ready = false; - + // Remove our hooks m_scene.EventManager.OnFrame -= SunUpdate; m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; @@ -419,6 +402,7 @@ namespace OpenSim.Region.CoreModules { get { return false; } } + #endregion #region EventManager Events @@ -446,9 +430,7 @@ namespace OpenSim.Region.CoreModules public void SunUpdate() { if (((m_frame++ % m_UpdateInterval) != 0) || !ready || m_SunFixed || !receivedEstateToolsSunUpdate) - { return; - } GenSunPos(); // Generate shared values once @@ -467,7 +449,7 @@ namespace OpenSim.Region.CoreModules } /// - /// + /// /// /// /// Is the sun's position fixed? @@ -484,7 +466,6 @@ namespace OpenSim.Region.CoreModules while (FixedSunHour < 0) FixedSunHour += 24; - m_SunFixedHour = FixedSunHour; m_SunFixed = FixedSun; @@ -499,14 +480,12 @@ namespace OpenSim.Region.CoreModules // When sun settings are updated, we should update all clients with new settings. SunUpdateToAllClients(); - m_log.DebugFormat("[SUN]: PosTime : {0}", PosTime.ToString()); } } #endregion - private void SunUpdateToAllClients() { m_scene.ForEachScenePresence(delegate(ScenePresence sp) @@ -553,7 +532,6 @@ namespace OpenSim.Region.CoreModules { float ticksleftover = CurrentTime % SecondsPerSunCycle; - return (24.0f * (ticksleftover / SecondsPerSunCycle)); } @@ -666,7 +644,6 @@ namespace OpenSim.Region.CoreModules // When sun settings are updated, we should update all clients with new settings. SunUpdateToAllClients(); - } return Output; diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 4feb3fc3de..c321a15866 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -296,7 +296,7 @@ namespace OpenSim.Region.Framework.Scenes /// ChatToClientsEvent is triggered via ChatModule (or /// substitutes thereof) when a chat message is actually sent to clients. Clients will only be sent a /// received chat message if they satisfy various conditions (within audible range, etc.) - /// + /// public delegate void ChatToClientsEvent( UUID senderID, HashSet receiverIDs, string message, ChatTypeEnum type, Vector3 fromPos, string fromName, @@ -1636,8 +1636,8 @@ namespace OpenSim.Region.Framework.Scenes e.Message, e.StackTrace); } } - } - } + } + } public void TriggerOnChatBroadcast(Object sender, OSChatMessage chat) { diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 95908fc274..e661ca9da1 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -804,7 +804,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization private static void ProcessShpTextureEntry(PrimitiveBaseShape shp, XmlTextReader reader) { byte[] teData = Convert.FromBase64String(reader.ReadElementString("TextureEntry")); - shp.Textures = new Primitive.TextureEntry(teData, 0, teData.Length); + shp.Textures = new Primitive.TextureEntry(teData, 0, teData.Length); } private static void ProcessShpExtraParams(PrimitiveBaseShape shp, XmlTextReader reader) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 25dba7f45e..3d34441a90 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -220,7 +220,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups groupID, groupMembers.Count); foreach (GroupMembersData member in groupMembers) - { + { if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) { // Don't deliver messages to people who have dropped this session @@ -266,7 +266,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups void OnClientLogin(IClientAPI client) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: OnInstantMessage registered for {0}", client.Name); + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: OnInstantMessage registered for {0}", client.Name); } private void OnNewClient(IClientAPI client) diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs index 2ddc31bd07..f47e71c151 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs @@ -50,7 +50,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; - + private readonly Dictionary m_scripts = new Dictionary(); private readonly Dictionary m_extensions = new Dictionary(); @@ -77,7 +77,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { m_log.Info("[MRM] Enabling MRM Module"); m_scene = scene; - + // when hidden, we don't listen for client initiated script events // only making the MRM engine available for region modules if (!source.Configs["MRM"].GetBoolean("Hidden", false)) @@ -85,7 +85,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule scene.EventManager.OnRezScript += EventManager_OnRezScript; scene.EventManager.OnStopScript += EventManager_OnStopScript; } - + scene.EventManager.OnFrame += EventManager_OnFrame; scene.RegisterModuleInterface(this); @@ -304,7 +304,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule public void PostInitialise() { - } public void Close() @@ -350,7 +349,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule if (!Directory.Exists(tmp)) Directory.CreateDirectory(tmp); - m_log.Info("MRM 2"); try @@ -396,8 +394,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule parameters.IncludeDebugInformation = true; - string rootPath = - Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory); + string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory); List libraries = new List(); string[] lines = Script.Split(new string[] {"\n"}, StringSplitOptions.RemoveEmptyEntries); From 5968d343bb21af4c73f1d925837560f953e5ef61 Mon Sep 17 00:00:00 2001 From: dahlia Date: Tue, 26 Oct 2010 21:19:33 -0700 Subject: [PATCH 49/51] Overload Scene.NewUserConnection() to facilitate NPCs and other region specific applications --- OpenSim/Region/Framework/Scenes/Scene.cs | 36 ++++++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 3dd0f3ac3d..f0ae45ee89 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3278,7 +3278,6 @@ namespace OpenSim.Region.Framework.Scenes m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", m_regInfo.RegionName); } - /// /// Do the work necessary to initiate a new user connection for a particular scene. /// At the moment, this consists of setting up the caps infrastructure @@ -3290,6 +3289,23 @@ namespace OpenSim.Region.Framework.Scenes /// True if the region accepts this agent. False if it does not. False will /// also return a reason. public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason) + { + return NewUserConnection(agent, teleportFlags, out reason, true); + } + + /// + /// Do the work necessary to initiate a new user connection for a particular scene. + /// At the moment, this consists of setting up the caps infrastructure + /// The return bool should allow for connections to be refused, but as not all calling paths + /// take proper notice of it let, we allowed banned users in still. + /// + /// CircuitData of the agent who is connecting + /// Outputs the reason for the false response on this string + /// True for normal presence. False for NPC + /// or other applications where a full grid/Hypergrid presence may not be required. + /// True if the region accepts this agent. False if it does not. False will + /// also return a reason. + public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) { bool vialogin = ((teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0 || (teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0); @@ -3339,16 +3355,18 @@ namespace OpenSim.Region.Framework.Scenes if (sp == null) // We don't have an [child] agent here already { - - try + if (requirePresenceLookup) { - if (!VerifyUserPresence(agent, out reason)) + try + { + if (!VerifyUserPresence(agent, out reason)) + return false; + } + catch (Exception e) + { + m_log.ErrorFormat("[CONNECTION BEGIN]: Exception verifying presence " + e.ToString()); return false; - } - catch (Exception e) - { - m_log.ErrorFormat("[CONNECTION BEGIN]: Exception verifying presence " + e.ToString()); - return false; + } } try From 1fcac7203d0e92f735d10c42681768521d712ea5 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 27 Oct 2010 20:47:27 +0100 Subject: [PATCH 50/51] Prevent nullrefs in scene object deletion. Mantis #5156 --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index f81c551768..24d73346ff 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -406,11 +406,14 @@ namespace OpenSim.Region.Framework.Scenes public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked) { EntityBase entity; - if (!Entities.TryGetValue(uuid, out entity) && entity is SceneObjectGroup) + if (!Entities.TryGetValue(uuid, out entity) || (!(entity is SceneObjectGroup))) return false; SceneObjectGroup grp = (SceneObjectGroup)entity; + if (entity == null) + return false; + if (!resultOfObjectLinked) { m_numPrim -= grp.PrimCount; From 727838f914d8e8aaf77df79356ef9d234ffc1b23 Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Thu, 28 Oct 2010 00:37:32 -0400 Subject: [PATCH 51/51] Formatting cleanup. --- .../OptionalModules/Scripting/Minimodule/ExtensionHandler.cs | 2 +- .../Region/OptionalModules/Scripting/Minimodule/MRMModule.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/ExtensionHandler.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/ExtensionHandler.cs index d8f7a84022..3f1bd54ee7 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/ExtensionHandler.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/ExtensionHandler.cs @@ -32,7 +32,7 @@ using OpenSim.Region.OptionalModules.Scripting.Minimodule.Interfaces; namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { - class ExtensionHandler : IExtension + class ExtensionHandler : IExtension { private readonly Dictionary m_instances; diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs index f47e71c151..df60709535 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs @@ -291,7 +291,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule public void InitializeMRM(MRMBase mmb, uint localID, UUID itemID) { - m_log.Info("[MRM] Created MRM Instance"); IWorld world;