From 25661b611d241534e5e8d7ce1731de8506481a7d Mon Sep 17 00:00:00 2001 From: MW Date: Sat, 21 Feb 2009 13:44:03 +0000 Subject: Refactored the GridServer into a GridDBService and a set of "modules". Currently they aren't plugin modules as the support for dynamically loading them isn't complete. --- OpenSim/Grid/GridServer/GridDBService.cs | 303 ++++++ OpenSim/Grid/GridServer/GridManager.cs | 1282 ----------------------- OpenSim/Grid/GridServer/GridMessagingModule.cs | 101 ++ OpenSim/Grid/GridServer/GridRestModule.cs | 269 +++++ OpenSim/Grid/GridServer/GridServerBase.cs | 121 ++- OpenSim/Grid/GridServer/GridXmlRpcModule.cs | 844 +++++++++++++++ OpenSim/Grid/GridServer/IGridCore.cs | 13 + OpenSim/Grid/GridServer/IGridMessagingModule.cs | 11 + 8 files changed, 1621 insertions(+), 1323 deletions(-) create mode 100644 OpenSim/Grid/GridServer/GridDBService.cs delete mode 100644 OpenSim/Grid/GridServer/GridManager.cs create mode 100644 OpenSim/Grid/GridServer/GridMessagingModule.cs create mode 100644 OpenSim/Grid/GridServer/GridRestModule.cs create mode 100644 OpenSim/Grid/GridServer/GridXmlRpcModule.cs create mode 100644 OpenSim/Grid/GridServer/IGridCore.cs create mode 100644 OpenSim/Grid/GridServer/IGridMessagingModule.cs diff --git a/OpenSim/Grid/GridServer/GridDBService.cs b/OpenSim/Grid/GridServer/GridDBService.cs new file mode 100644 index 0000000..389cf69 --- /dev/null +++ b/OpenSim/Grid/GridServer/GridDBService.cs @@ -0,0 +1,303 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; +using log4net; +using Nwc.XmlRpc; +using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Servers; + + +namespace OpenSim.Grid.GridServer +{ + public class GridDBService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private List _plugins = new List(); + private List _logplugins = new List(); + + /// + /// Adds a list of grid and log data plugins, as described by + /// `provider' and `connect', to `_plugins' and `_logplugins', + /// respectively. + /// + /// + /// The filename of the inventory server plugin DLL. + /// + /// + /// The connection string for the storage backend. + /// + public void AddPlugin(string provider, string connect) + { + _plugins = DataPluginFactory.LoadDataPlugins(provider, connect); + _logplugins = DataPluginFactory.LoadDataPlugins(provider, connect); + } + + public int GetNumberOfPlugins() + { + return _plugins.Count; + } + + /// + /// Logs a piece of information to the database + /// + /// What you were operating on (in grid server, this will likely be the region UUIDs) + /// Which method is being called? + /// What arguments are being passed? + /// How high priority is this? 1 = Max, 6 = Verbose + /// The message to log + private void logToDB(string target, string method, string args, int priority, string message) + { + foreach (ILogDataPlugin plugin in _logplugins) + { + try + { + plugin.saveLog("Gridserver", target, method, args, priority, message); + } + catch (Exception) + { + m_log.Warn("[storage]: Unable to write log via " + plugin.Name); + } + } + } + + /// + /// Returns a region by argument + /// + /// A UUID key of the region to return + /// A SimProfileData for the region + public RegionProfileData GetRegion(UUID uuid) + { + foreach (IGridDataPlugin plugin in _plugins) + { + try + { + return plugin.GetProfileByUUID(uuid); + } + catch (Exception e) + { + m_log.Warn("[storage]: GetRegion - " + e.Message); + } + } + return null; + } + + /// + /// Returns a region by argument + /// + /// A regionHandle of the region to return + /// A SimProfileData for the region + public RegionProfileData GetRegion(ulong handle) + { + foreach (IGridDataPlugin plugin in _plugins) + { + try + { + return plugin.GetProfileByHandle(handle); + } + catch (Exception ex) + { + m_log.Debug("[storage]: " + ex.Message); + m_log.Warn("[storage]: Unable to find region " + handle.ToString() + " via " + plugin.Name); + } + } + return null; + } + + /// + /// Returns a region by argument + /// + /// A partial regionName of the region to return + /// A SimProfileData for the region + public RegionProfileData GetRegion(string regionName) + { + foreach (IGridDataPlugin plugin in _plugins) + { + try + { + return plugin.GetProfileByString(regionName); + } + catch + { + m_log.Warn("[storage]: Unable to find region " + regionName + " via " + plugin.Name); + } + } + return null; + } + + public List GetRegions(uint xmin, uint ymin, uint xmax, uint ymax) + { + List regions = new List(); + + foreach (IGridDataPlugin plugin in _plugins) + { + try + { + regions.AddRange(plugin.GetProfilesInRange(xmin, ymin, xmax, ymax)); + } + catch + { + m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); + } + } + + return regions; + } + + public List GetRegions(string name, int maxNum) + { + List regions = new List(); + foreach (IGridDataPlugin plugin in _plugins) + { + try + { + int num = maxNum - regions.Count; + List profiles = plugin.GetRegionsByName(name, (uint)num); + if (profiles != null) regions.AddRange(profiles); + } + catch + { + m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); + } + } + + return regions; + } + + public void LoginRegion(RegionProfileData sim, RegionProfileData existingSim) + { + foreach (IGridDataPlugin plugin in _plugins) + { + try + { + DataResponse insertResponse; + + if (existingSim == null) + { + insertResponse = plugin.AddProfile(sim); + } + else + { + insertResponse = plugin.UpdateProfile(sim); + } + + switch (insertResponse) + { + case DataResponse.RESPONSE_OK: + m_log.Info("[LOGIN END]: " + (existingSim == null ? "New" : "Existing") + " sim login successful: " + sim.regionName); + break; + case DataResponse.RESPONSE_ERROR: + m_log.Warn("[LOGIN END]: Sim login failed (Error): " + sim.regionName); + break; + case DataResponse.RESPONSE_INVALIDCREDENTIALS: + m_log.Warn("[LOGIN END]: " + + "Sim login failed (Invalid Credentials): " + sim.regionName); + break; + case DataResponse.RESPONSE_AUTHREQUIRED: + m_log.Warn("[LOGIN END]: " + + "Sim login failed (Authentication Required): " + + sim.regionName); + break; + } + } + catch (Exception e) + { + m_log.Warn("[LOGIN END]: " + + "Unable to login region " + sim.ToString() + " via " + plugin.Name); + m_log.Warn("[LOGIN END]: " + e.ToString()); + } + } + } + + public DataResponse DeleteRegion(string uuid) + { + DataResponse insertResponse = DataResponse.RESPONSE_ERROR; + foreach (IGridDataPlugin plugin in _plugins) + { + //OpenSim.Data.MySQL.MySQLGridData dbengine = new OpenSim.Data.MySQL.MySQLGridData(); + try + { + //Nice are we not using multiple databases? + //MySQLGridData mysqldata = (MySQLGridData)(plugin); + + //DataResponse insertResponse = mysqldata.DeleteProfile(TheSim); + insertResponse = plugin.DeleteProfile(uuid); + } + catch (Exception) + { + m_log.Error("storage Unable to delete region " + uuid + " via " + plugin.Name); + //MainLog.Instance.Warn("storage", e.ToString()); + insertResponse = DataResponse.RESPONSE_ERROR; + } + } + return insertResponse; + } + + public string CheckReservations(RegionProfileData theSim, XmlNode authkeynode) + { + foreach (IGridDataPlugin plugin in _plugins) + { + try + { + //Check reservations + ReservationData reserveData = + plugin.GetReservationAtPoint(theSim.regionLocX, theSim.regionLocY); + if ((reserveData != null && reserveData.gridRecvKey == theSim.regionRecvKey) || + (reserveData == null && authkeynode.InnerText != theSim.regionRecvKey)) + { + plugin.AddProfile(theSim); + m_log.Info("[grid]: New sim added to grid (" + theSim.regionName + ")"); + logToDB(theSim.ToString(), "RestSetSimMethod", String.Empty, 5, + "Region successfully updated and connected to grid."); + } + else + { + m_log.Warn("[grid]: " + + "Unable to update region (RestSetSimMethod): Incorrect reservation auth key."); + // Wanted: " + reserveData.gridRecvKey + ", Got: " + theSim.regionRecvKey + "."); + return "Unable to update region (RestSetSimMethod): Incorrect auth key."; + } + } + catch (Exception e) + { + m_log.Warn("[GRID]: GetRegionPlugin Handle " + plugin.Name + " unable to add new sim: " + + e.ToString()); + } + } + return "OK"; + } + } +} diff --git a/OpenSim/Grid/GridServer/GridManager.cs b/OpenSim/Grid/GridServer/GridManager.cs deleted file mode 100644 index 5dc186c..0000000 --- a/OpenSim/Grid/GridServer/GridManager.cs +++ /dev/null @@ -1,1282 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Xml; -using log4net; -using Nwc.XmlRpc; -using OpenMetaverse; -using OpenSim.Data; -using OpenSim.Framework; -using OpenSim.Framework.Communications; -using OpenSim.Framework.Servers; - -namespace OpenSim.Grid.GridServer -{ - public class GridManager - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private List _plugins = new List(); - private List _logplugins = new List(); - - // This is here so that the grid server can hand out MessageServer settings to regions on registration - private List _MessageServers = new List(); - - public GridConfig Config; - - /// - /// Used to notify old regions as to which OpenSim version to upgrade to - /// - private string m_opensimVersion; - - /// - /// Constructor - /// - /// - /// Used to notify old regions as to which OpenSim version to upgrade to - /// - public GridManager(string opensimVersion) - { - m_opensimVersion = opensimVersion; - } - - /// - /// Adds a list of grid and log data plugins, as described by - /// `provider' and `connect', to `_plugins' and `_logplugins', - /// respectively. - /// - /// - /// The filename of the inventory server plugin DLL. - /// - /// - /// The connection string for the storage backend. - /// - public void AddPlugin(string provider, string connect) - { - _plugins = DataPluginFactory.LoadDataPlugins(provider, connect); - _logplugins = DataPluginFactory.LoadDataPlugins(provider, connect); - } - - /// - /// Logs a piece of information to the database - /// - /// What you were operating on (in grid server, this will likely be the region UUIDs) - /// Which method is being called? - /// What arguments are being passed? - /// How high priority is this? 1 = Max, 6 = Verbose - /// The message to log - private void logToDB(string target, string method, string args, int priority, string message) - { - foreach (ILogDataPlugin plugin in _logplugins) - { - try - { - plugin.saveLog("Gridserver", target, method, args, priority, message); - } - catch (Exception) - { - m_log.Warn("[storage]: Unable to write log via " + plugin.Name); - } - } - } - - /// - /// Returns a region by argument - /// - /// A UUID key of the region to return - /// A SimProfileData for the region - public RegionProfileData GetRegion(UUID uuid) - { - foreach (IGridDataPlugin plugin in _plugins) - { - try - { - return plugin.GetProfileByUUID(uuid); - } - catch (Exception e) - { - m_log.Warn("[storage]: GetRegion - " + e.Message); - } - } - return null; - } - - /// - /// Returns a region by argument - /// - /// A regionHandle of the region to return - /// A SimProfileData for the region - public RegionProfileData GetRegion(ulong handle) - { - foreach (IGridDataPlugin plugin in _plugins) - { - try - { - return plugin.GetProfileByHandle(handle); - } - catch (Exception ex) - { - m_log.Debug("[storage]: " + ex.Message); - m_log.Warn("[storage]: Unable to find region " + handle.ToString() + " via " + plugin.Name); - } - } - return null; - } - - /// - /// Returns a region by argument - /// - /// A partial regionName of the region to return - /// A SimProfileData for the region - public RegionProfileData GetRegion(string regionName) - { - foreach (IGridDataPlugin plugin in _plugins) - { - try - { - return plugin.GetProfileByString(regionName); - } - catch - { - m_log.Warn("[storage]: Unable to find region " + regionName + " via " + plugin.Name); - } - } - return null; - } - - public List GetRegions(uint xmin, uint ymin, uint xmax, uint ymax) - { - List regions = new List(); - - foreach (IGridDataPlugin plugin in _plugins) - { - try - { - regions.AddRange(plugin.GetProfilesInRange(xmin, ymin, xmax, ymax)); - } - catch - { - m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); - } - } - - return regions; - } - - public List GetRegions(string name, int maxNum) - { - List regions = new List(); - foreach (IGridDataPlugin plugin in _plugins) - { - try - { - int num = maxNum - regions.Count; - List profiles = plugin.GetRegionsByName(name, (uint)num); - if (profiles != null) regions.AddRange(profiles); - } - catch - { - m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); - } - } - - return regions; - } - - /// - /// Returns a XML String containing a list of the neighbouring regions - /// - /// The regionhandle for the center sim - /// An XML string containing neighbour entities - public string GetXMLNeighbours(ulong reqhandle) - { - string response = String.Empty; - RegionProfileData central_region = GetRegion(reqhandle); - RegionProfileData neighbour; - for (int x = -1; x < 2; x++) - { - for (int y = -1; y < 2; y++) - { - if ( - GetRegion( - Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), - (uint)(central_region.regionLocY + y) * Constants.RegionSize)) != null) - { - neighbour = - GetRegion( - Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), - (uint)(central_region.regionLocY + y) * Constants.RegionSize)); - - response += ""; - response += "" + neighbour.serverIP + ""; - response += "" + neighbour.serverPort.ToString() + ""; - response += "" + neighbour.regionLocX.ToString() + ""; - response += "" + neighbour.regionLocY.ToString() + ""; - response += "" + neighbour.regionHandle.ToString() + ""; - response += ""; - } - } - } - return response; - } - - /// - /// Checks that it's valid to replace the existing region data with new data - /// - /// Currently, this means ensure that the keys passed in by the new region - /// match those in the original region. (XXX Is this correct? Shouldn't we simply check - /// against the keys in the current configuration?) - /// - /// - /// - protected virtual void ValidateOverwriteKeys(RegionProfileData sim, RegionProfileData existingSim) - { - if (!(existingSim.regionRecvKey == sim.regionRecvKey && existingSim.regionSendKey == sim.regionSendKey)) - { - throw new LoginException( - String.Format( - "Authentication failed when trying to login existing region {0} at location {1} {2} currently occupied by {3}" - + " with the region's send key {4} (expected {5}) and the region's receive key {6} (expected {7})", - sim.regionName, sim.regionLocX, sim.regionLocY, existingSim.regionName, - sim.regionSendKey, existingSim.regionSendKey, sim.regionRecvKey, existingSim.regionRecvKey), - "The keys required to login your region did not match the grid server keys. Please check your grid send and receive keys."); - } - } - - /// - /// Checks that the new region data is valid. - /// - /// Currently, this means checking that the keys passed in by the new region - /// match those in the grid server's configuration. - /// - /// - /// - /// Thrown if region login failed - protected virtual void ValidateNewRegionKeys(RegionProfileData sim) - { - if (!(sim.regionRecvKey == Config.SimSendKey && sim.regionSendKey == Config.SimRecvKey)) - { - throw new LoginException( - String.Format( - "Authentication failed when trying to login new region {0} at location {1} {2}" - + " with the region's send key {3} (expected {4}) and the region's receive key {5} (expected {6})", - sim.regionName, sim.regionLocX, sim.regionLocY, - sim.regionSendKey, Config.SimRecvKey, sim.regionRecvKey, Config.SimSendKey), - "The keys required to login your region did not match your existing region keys. Please check your grid send and receive keys."); - } - } - - /// - /// Check that a region's http uri is externally contactable. - /// - /// - /// Thrown if the region is not contactable - protected virtual void ValidateRegionContactable(RegionProfileData sim) - { - string regionStatusUrl = String.Format("{0}{1}", sim.httpServerURI, "simstatus/"); - string regionStatusResponse; - - RestClient rc = new RestClient(regionStatusUrl); - rc.RequestMethod = "GET"; - - m_log.DebugFormat("[LOGIN]: Contacting {0} for status of region {1}", regionStatusUrl, sim.regionName); - - try - { - Stream rs = rc.Request(); - StreamReader sr = new StreamReader(rs); - regionStatusResponse = sr.ReadToEnd(); - sr.Close(); - } - catch (Exception e) - { - throw new LoginException( - String.Format("Region status request to {0} failed", regionStatusUrl), - String.Format( - "The grid service could not contact the http url {0} at your region. Please make sure this url is reachable by the grid service", - regionStatusUrl), - e); - } - - if (!regionStatusResponse.Equals("OK")) - { - throw new LoginException( - String.Format( - "Region {0} at {1} returned status response {2} rather than {3}", - sim.regionName, regionStatusUrl, regionStatusResponse, "OK"), - String.Format( - "When the grid service asked for the status of your region, it received the response {0} rather than {1}. Please check your status", - regionStatusResponse, "OK")); - } - } - - /// - /// Construct an XMLRPC error response - /// - /// - /// - public static XmlRpcResponse ErrorResponse(string error) - { - XmlRpcResponse errorResponse = new XmlRpcResponse(); - Hashtable errorResponseData = new Hashtable(); - errorResponse.Value = errorResponseData; - errorResponseData["error"] = error; - return errorResponse; - } - - /// - /// Performed when a region connects to the grid server initially. - /// - /// The XML RPC Request - /// Startup parameters - public XmlRpcResponse XmlRpcSimulatorLoginMethod(XmlRpcRequest request) - { - RegionProfileData sim; - RegionProfileData existingSim; - - Hashtable requestData = (Hashtable)request.Params[0]; - UUID uuid; - - if (!requestData.ContainsKey("UUID") || !UUID.TryParse((string)requestData["UUID"], out uuid)) - { - m_log.Debug("[LOGIN PRELUDE]: Region connected without a UUID, sending back error response."); - return ErrorResponse("No UUID passed to grid server - unable to connect you"); - } - - try - { - sim = RegionFromRequest(requestData); - } - catch (FormatException e) - { - m_log.Debug("[LOGIN PRELUDE]: Invalid login parameters, sending back error response."); - return ErrorResponse("Wrong format in login parameters. Please verify parameters." + e.ToString()); - } - - m_log.InfoFormat("[LOGIN BEGIN]: Received login request from simulator: {0}", sim.regionName); - - if (!Config.AllowRegionRegistration) - { - m_log.DebugFormat( - "[LOGIN END]: Disabled region registration blocked login request from simulator: {0}", - sim.regionName); - - return ErrorResponse("This grid is currently not accepting region registrations."); - } - - int majorInterfaceVersion = 0; - if (requestData.ContainsKey("major_interface_version")) - int.TryParse((string)requestData["major_interface_version"], out majorInterfaceVersion); - - if (majorInterfaceVersion != VersionInfo.MajorInterfaceVersion) - { - return ErrorResponse( - String.Format( - "Your region service implements OGS1 interface version {0}" - + " but this grid requires that the region implement OGS1 interface version {1} to connect." - + " Try changing to OpenSimulator {2}", - majorInterfaceVersion, VersionInfo.MajorInterfaceVersion, m_opensimVersion)); - } - - existingSim = GetRegion(sim.regionHandle); - - if (existingSim == null || existingSim.UUID == sim.UUID || sim.UUID != sim.originUUID) - { - try - { - if (existingSim == null) - { - ValidateNewRegionKeys(sim); - } - else - { - ValidateOverwriteKeys(sim, existingSim); - } - - ValidateRegionContactable(sim); - } - catch (LoginException e) - { - string logMsg = e.Message; - if (e.InnerException != null) - logMsg += ", " + e.InnerException.Message; - - m_log.WarnFormat("[LOGIN END]: {0}", logMsg); - - return e.XmlRpcErrorResponse; - } - - foreach (IGridDataPlugin plugin in _plugins) - { - try - { - DataResponse insertResponse; - - if (existingSim == null) - { - insertResponse = plugin.AddProfile(sim); - } - else - { - insertResponse = plugin.UpdateProfile(sim); - } - - switch (insertResponse) - { - case DataResponse.RESPONSE_OK: - m_log.Info("[LOGIN END]: " + (existingSim == null ? "New" : "Existing") + " sim login successful: " + sim.regionName); - break; - case DataResponse.RESPONSE_ERROR: - m_log.Warn("[LOGIN END]: Sim login failed (Error): " + sim.regionName); - break; - case DataResponse.RESPONSE_INVALIDCREDENTIALS: - m_log.Warn("[LOGIN END]: " + - "Sim login failed (Invalid Credentials): " + sim.regionName); - break; - case DataResponse.RESPONSE_AUTHREQUIRED: - m_log.Warn("[LOGIN END]: " + - "Sim login failed (Authentication Required): " + - sim.regionName); - break; - } - } - catch (Exception e) - { - m_log.Warn("[LOGIN END]: " + - "Unable to login region " + sim.ToString() + " via " + plugin.Name); - m_log.Warn("[LOGIN END]: " + e.ToString()); - } - } - - XmlRpcResponse response = CreateLoginResponse(sim); - - return response; - } - else - { - m_log.Warn("[LOGIN END]: Failed to login region " + sim.regionName + " at location " + sim.regionLocX + " " + sim.regionLocY + " currently occupied by " + existingSim.regionName); - return ErrorResponse("Another region already exists at that location. Please try another."); - } - } - - /// - /// Construct a successful response to a simulator's login attempt. - /// - /// - /// - private XmlRpcResponse CreateLoginResponse(RegionProfileData sim) - { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - response.Value = responseData; - - ArrayList SimNeighboursData = GetSimNeighboursData(sim); - - responseData["UUID"] = sim.UUID.ToString(); - responseData["region_locx"] = sim.regionLocX.ToString(); - responseData["region_locy"] = sim.regionLocY.ToString(); - responseData["regionname"] = sim.regionName; - responseData["estate_id"] = "1"; - responseData["neighbours"] = SimNeighboursData; - - responseData["sim_ip"] = sim.serverIP; - responseData["sim_port"] = sim.serverPort.ToString(); - responseData["asset_url"] = sim.regionAssetURI; - responseData["asset_sendkey"] = sim.regionAssetSendKey; - responseData["asset_recvkey"] = sim.regionAssetRecvKey; - responseData["user_url"] = sim.regionUserURI; - responseData["user_sendkey"] = sim.regionUserSendKey; - responseData["user_recvkey"] = sim.regionUserRecvKey; - responseData["authkey"] = sim.regionSecret; - - // New! If set, use as URL to local sim storage (ie http://remotehost/region.Yap) - responseData["data_uri"] = sim.regionDataURI; - - responseData["allow_forceful_banlines"] = Config.AllowForcefulBanlines; - - // Instead of sending a multitude of message servers to the registering sim - // we should probably be sending a single one and parhaps it's backup - // that has responsibility over routing it's messages. - - // The Sim won't be contacting us again about any of the message server stuff during it's time up. - - responseData["messageserver_count"] = _MessageServers.Count; - - for (int i = 0; i < _MessageServers.Count; i++) - { - responseData["messageserver_uri" + i] = _MessageServers[i].URI; - responseData["messageserver_sendkey" + i] = _MessageServers[i].sendkey; - responseData["messageserver_recvkey" + i] = _MessageServers[i].recvkey; - } - return response; - } - - private ArrayList GetSimNeighboursData(RegionProfileData sim) - { - ArrayList SimNeighboursData = new ArrayList(); - - RegionProfileData neighbour; - Hashtable NeighbourBlock; - - //First use the fast method. (not implemented in SQLLite) - List neighbours = GetRegions(sim.regionLocX - 1, sim.regionLocY - 1, sim.regionLocX + 1, sim.regionLocY + 1); - - if (neighbours.Count > 0) - { - foreach (RegionProfileData aSim in neighbours) - { - NeighbourBlock = new Hashtable(); - NeighbourBlock["sim_ip"] = aSim.serverIP; - NeighbourBlock["sim_port"] = aSim.serverPort.ToString(); - NeighbourBlock["region_locx"] = aSim.regionLocX.ToString(); - NeighbourBlock["region_locy"] = aSim.regionLocY.ToString(); - NeighbourBlock["UUID"] = aSim.ToString(); - NeighbourBlock["regionHandle"] = aSim.regionHandle.ToString(); - - if (aSim.UUID != sim.UUID) - { - SimNeighboursData.Add(NeighbourBlock); - } - } - } - else - { - for (int x = -1; x < 2; x++) - { - for (int y = -1; y < 2; y++) - { - if ( - GetRegion( - Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), - (uint)(sim.regionLocY + y) * Constants.RegionSize)) != null) - { - neighbour = - GetRegion( - Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), - (uint)(sim.regionLocY + y) * Constants.RegionSize)); - - NeighbourBlock = new Hashtable(); - NeighbourBlock["sim_ip"] = neighbour.serverIP; - NeighbourBlock["sim_port"] = neighbour.serverPort.ToString(); - NeighbourBlock["region_locx"] = neighbour.regionLocX.ToString(); - NeighbourBlock["region_locy"] = neighbour.regionLocY.ToString(); - NeighbourBlock["UUID"] = neighbour.UUID.ToString(); - NeighbourBlock["regionHandle"] = neighbour.regionHandle.ToString(); - - if (neighbour.UUID != sim.UUID) SimNeighboursData.Add(NeighbourBlock); - } - } - } - } - return SimNeighboursData; - } - - /// - /// Loads the grid's own RegionProfileData object with data from the XMLRPC simulator_login request from a region - /// - /// - /// - private RegionProfileData RegionFromRequest(Hashtable requestData) - { - RegionProfileData sim; - sim = new RegionProfileData(); - - sim.UUID = new UUID((string)requestData["UUID"]); - sim.originUUID = new UUID((string)requestData["originUUID"]); - - sim.regionRecvKey = String.Empty; - sim.regionSendKey = String.Empty; - - if (requestData.ContainsKey("region_secret")) - { - string regionsecret = (string)requestData["region_secret"]; - if (regionsecret.Length > 0) - sim.regionSecret = regionsecret; - else - sim.regionSecret = Config.SimRecvKey; - - } - else - { - sim.regionSecret = Config.SimRecvKey; - } - - sim.regionDataURI = String.Empty; - sim.regionAssetURI = Config.DefaultAssetServer; - sim.regionAssetRecvKey = Config.AssetRecvKey; - sim.regionAssetSendKey = Config.AssetSendKey; - sim.regionUserURI = Config.DefaultUserServer; - sim.regionUserSendKey = Config.UserSendKey; - sim.regionUserRecvKey = Config.UserRecvKey; - - sim.serverIP = (string)requestData["sim_ip"]; - sim.serverPort = Convert.ToUInt32((string)requestData["sim_port"]); - sim.httpPort = Convert.ToUInt32((string)requestData["http_port"]); - sim.remotingPort = Convert.ToUInt32((string)requestData["remoting_port"]); - sim.regionLocX = Convert.ToUInt32((string)requestData["region_locx"]); - sim.regionLocY = Convert.ToUInt32((string)requestData["region_locy"]); - sim.regionLocZ = 0; - - UUID textureID; - if (UUID.TryParse((string)requestData["map-image-id"], out textureID)) - { - sim.regionMapTextureID = textureID; - } - - // part of an initial brutish effort to provide accurate information (as per the xml region spec) - // wrt the ownership of a given region - // the (very bad) assumption is that this value is being read and handled inconsistently or - // not at all. Current strategy is to put the code in place to support the validity of this information - // and to roll forward debugging any issues from that point - // - // this particular section of the mod attempts to receive a value from the region's xml file by way of - // OSG1GridServices for the region's owner - sim.owner_uuid = (UUID)(string)requestData["master_avatar_uuid"]; - - try - { - sim.regionRecvKey = (string)requestData["recvkey"]; - sim.regionSendKey = (string)requestData["authkey"]; - } - catch (KeyNotFoundException) { } - - sim.regionHandle = Utils.UIntsToLong((sim.regionLocX * Constants.RegionSize), (sim.regionLocY * Constants.RegionSize)); - sim.serverURI = (string)requestData["server_uri"]; - - sim.httpServerURI = "http://" + sim.serverIP + ":" + sim.httpPort + "/"; - - sim.regionName = (string)requestData["sim_name"]; - return sim; - } - - /// - /// Returns an XML RPC response to a simulator profile request - /// Performed after moving a region. - /// - /// - /// - /// The XMLRPC Request - /// Processing parameters - public XmlRpcResponse XmlRpcDeleteRegionMethod(XmlRpcRequest request) - { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - response.Value = responseData; - - //RegionProfileData TheSim = null; - string uuid; - Hashtable requestData = (Hashtable)request.Params[0]; - - if (requestData.ContainsKey("UUID")) - { - //TheSim = GetRegion(new UUID((string) requestData["UUID"])); - uuid = requestData["UUID"].ToString(); - m_log.InfoFormat("[LOGOUT]: Logging out region: {0}", uuid); -// logToDB((new LLUUID((string)requestData["UUID"])).ToString(),"XmlRpcDeleteRegionMethod","", 5,"Attempting delete with UUID."); - } - else - { - responseData["error"] = "No UUID or region_handle passed to grid server - unable to delete"; - return response; - } - - foreach (IGridDataPlugin plugin in _plugins) - { - //OpenSim.Data.MySQL.MySQLGridData dbengine = new OpenSim.Data.MySQL.MySQLGridData(); - try - { - //Nice are we not using multiple databases? - //MySQLGridData mysqldata = (MySQLGridData)(plugin); - - //DataResponse insertResponse = mysqldata.DeleteProfile(TheSim); - DataResponse insertResponse = plugin.DeleteProfile(uuid); - - switch (insertResponse) - { - case DataResponse.RESPONSE_OK: - //MainLog.Instance.Verbose("grid", "Deleting region successful: " + uuid); - responseData["status"] = "Deleting region successful: " + uuid; - break; - case DataResponse.RESPONSE_ERROR: - //MainLog.Instance.Warn("storage", "Deleting region failed (Error): " + uuid); - responseData["status"] = "Deleting region failed (Error): " + uuid; - break; - case DataResponse.RESPONSE_INVALIDCREDENTIALS: - //MainLog.Instance.Warn("storage", "Deleting region failed (Invalid Credentials): " + uuid); - responseData["status"] = "Deleting region (Invalid Credentials): " + uuid; - break; - case DataResponse.RESPONSE_AUTHREQUIRED: - //MainLog.Instance.Warn("storage", "Deleting region failed (Authentication Required): " + uuid); - responseData["status"] = "Deleting region (Authentication Required): " + uuid; - break; - } - } - catch (Exception) - { - m_log.Error("storage Unable to delete region " + uuid + " via " + plugin.Name); - //MainLog.Instance.Warn("storage", e.ToString()); - } - } - - return response; - } - - /// - /// Returns an XML RPC response to a simulator profile request - /// - /// - /// - public XmlRpcResponse XmlRpcSimulatorDataRequestMethod(XmlRpcRequest request) - { - Hashtable requestData = (Hashtable)request.Params[0]; - Hashtable responseData = new Hashtable(); - RegionProfileData simData = null; - if (requestData.ContainsKey("region_UUID")) - { - UUID regionID = new UUID((string)requestData["region_UUID"]); - simData = GetRegion(regionID); - if (simData == null) - { - m_log.WarnFormat("[DATA] didn't find region for regionID {0} from {1}", - regionID, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); - } - } - else if (requestData.ContainsKey("region_handle")) - { - //CFK: The if/else below this makes this message redundant. - //CFK: Console.WriteLine("requesting data for region " + (string) requestData["region_handle"]); - ulong regionHandle = Convert.ToUInt64((string)requestData["region_handle"]); - simData = GetRegion(regionHandle); - if (simData == null) - { - m_log.WarnFormat("[DATA] didn't find region for regionHandle {0} from {1}", - regionHandle, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); - } - } - else if (requestData.ContainsKey("region_name_search")) - { - string regionName = (string)requestData["region_name_search"]; - simData = GetRegion(regionName); - if (simData == null) - { - m_log.WarnFormat("[DATA] didn't find region for regionName {0} from {1}", - regionName, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); - } - } - else m_log.Warn("[DATA] regionlookup without regionID, regionHandle or regionHame"); - - if (simData == null) - { - //Sim does not exist - responseData["error"] = "Sim does not exist"; - } - else - { - m_log.Info("[DATA]: found " + (string)simData.regionName + " regionHandle = " + - (string)requestData["region_handle"]); - responseData["sim_ip"] = simData.serverIP; - responseData["sim_port"] = simData.serverPort.ToString(); - responseData["server_uri"] = simData.serverURI; - responseData["http_port"] = simData.httpPort.ToString(); - responseData["remoting_port"] = simData.remotingPort.ToString(); - responseData["region_locx"] = simData.regionLocX.ToString(); - responseData["region_locy"] = simData.regionLocY.ToString(); - responseData["region_UUID"] = simData.UUID.Guid.ToString(); - responseData["region_name"] = simData.regionName; - responseData["regionHandle"] = simData.regionHandle.ToString(); - } - - XmlRpcResponse response = new XmlRpcResponse(); - response.Value = responseData; - return response; - } - - public XmlRpcResponse XmlRpcMapBlockMethod(XmlRpcRequest request) - { - int xmin = 980, ymin = 980, xmax = 1020, ymax = 1020; - - Hashtable requestData = (Hashtable)request.Params[0]; - if (requestData.ContainsKey("xmin")) - { - xmin = (Int32)requestData["xmin"]; - } - if (requestData.ContainsKey("ymin")) - { - ymin = (Int32)requestData["ymin"]; - } - if (requestData.ContainsKey("xmax")) - { - xmax = (Int32)requestData["xmax"]; - } - if (requestData.ContainsKey("ymax")) - { - ymax = (Int32)requestData["ymax"]; - } - //CFK: The second log is more meaningful and either standard or fast generally occurs. - //CFK: m_log.Info("[MAP]: World map request for range (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - response.Value = responseData; - IList simProfileList = new ArrayList(); - - bool fastMode = (Config.DatabaseProvider == "OpenSim.Data.MySQL.dll" || Config.DatabaseProvider == "OpenSim.Data.MSSQL.dll"); - - if (fastMode) - { - List neighbours = GetRegions((uint)xmin, (uint)ymin, (uint)xmax, (uint)ymax); - - foreach (RegionProfileData aSim in neighbours) - { - Hashtable simProfileBlock = new Hashtable(); - simProfileBlock["x"] = aSim.regionLocX.ToString(); - simProfileBlock["y"] = aSim.regionLocY.ToString(); - //m_log.DebugFormat("[MAP]: Sending neighbour info for {0},{1}", aSim.regionLocX, aSim.regionLocY); - simProfileBlock["name"] = aSim.regionName; - simProfileBlock["access"] = 21; - simProfileBlock["region-flags"] = 512; - simProfileBlock["water-height"] = 0; - simProfileBlock["agents"] = 1; - simProfileBlock["map-image-id"] = aSim.regionMapTextureID.ToString(); - - // For Sugilite compatibility - simProfileBlock["regionhandle"] = aSim.regionHandle.ToString(); - simProfileBlock["sim_ip"] = aSim.serverIP; - simProfileBlock["sim_port"] = aSim.serverPort.ToString(); - simProfileBlock["sim_uri"] = aSim.serverURI.ToString(); - simProfileBlock["uuid"] = aSim.UUID.ToString(); - simProfileBlock["remoting_port"] = aSim.remotingPort.ToString(); - simProfileBlock["http_port"] = aSim.httpPort.ToString(); - - simProfileList.Add(simProfileBlock); - } - m_log.Info("[MAP]: Fast map " + simProfileList.Count.ToString() + - " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); - } - else - { - RegionProfileData simProfile; - for (int x = xmin; x < xmax + 1; x++) - { - for (int y = ymin; y < ymax + 1; y++) - { - ulong regHandle = Utils.UIntsToLong((uint)(x * Constants.RegionSize), (uint)(y * Constants.RegionSize)); - simProfile = GetRegion(regHandle); - if (simProfile != null) - { - Hashtable simProfileBlock = new Hashtable(); - simProfileBlock["x"] = x; - simProfileBlock["y"] = y; - simProfileBlock["name"] = simProfile.regionName; - simProfileBlock["access"] = 0; - simProfileBlock["region-flags"] = 0; - simProfileBlock["water-height"] = 20; - simProfileBlock["agents"] = 1; - simProfileBlock["map-image-id"] = simProfile.regionMapTextureID.ToString(); - - // For Sugilite compatibility - simProfileBlock["regionhandle"] = simProfile.regionHandle.ToString(); - simProfileBlock["sim_ip"] = simProfile.serverIP.ToString(); - simProfileBlock["sim_port"] = simProfile.serverPort.ToString(); - simProfileBlock["sim_uri"] = simProfile.serverURI.ToString(); - simProfileBlock["uuid"] = simProfile.UUID.ToString(); - simProfileBlock["remoting_port"] = simProfile.remotingPort.ToString(); - simProfileBlock["http_port"] = simProfile.httpPort; - - simProfileList.Add(simProfileBlock); - } - } - } - m_log.Info("[MAP]: Std map " + simProfileList.Count.ToString() + - " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); - } - - responseData["sim-profiles"] = simProfileList; - - return response; - } - - /// - /// Returns up to maxNumber profiles of regions that have a name starting with name - /// - /// - /// - public XmlRpcResponse XmlRpcSearchForRegionMethod(XmlRpcRequest request) - { - Hashtable requestData = (Hashtable)request.Params[0]; - - if (!requestData.ContainsKey("name") || !requestData.Contains("maxNumber")) - { - m_log.Warn("[DATA] Invalid region-search request; missing name or maxNumber"); - return new XmlRpcResponse(500, "Missing name or maxNumber in region search request"); - } - - Hashtable responseData = new Hashtable(); - - string name = (string)requestData["name"]; - int maxNumber = Convert.ToInt32((string)requestData["maxNumber"]); - if (maxNumber == 0 || name.Length < 3) - { - // either we didn't want any, or we were too unspecific - responseData["numFound"] = 0; - } - else - { - List sims = GetRegions(name, maxNumber); - - responseData["numFound"] = sims.Count; - for (int i = 0; i < sims.Count; ++i) - { - RegionProfileData sim = sims[i]; - string prefix = "region" + i + "."; - responseData[prefix + "region_name"] = sim.regionName; - responseData[prefix + "region_UUID"] = sim.UUID.ToString(); - responseData[prefix + "region_locx"] = sim.regionLocX.ToString(); - responseData[prefix + "region_locy"] = sim.regionLocY.ToString(); - responseData[prefix + "sim_ip"] = sim.serverIP.ToString(); - responseData[prefix + "sim_port"] = sim.serverPort.ToString(); - responseData[prefix + "remoting_port"] = sim.remotingPort.ToString(); - responseData[prefix + "http_port"] = sim.httpPort.ToString(); - responseData[prefix + "map_UUID"] = sim.regionMapTextureID.ToString(); - } - } - - XmlRpcResponse response = new XmlRpcResponse(); - response.Value = responseData; - return response; - } - - /// - /// Performs a REST Get Operation - /// - /// - /// - /// - /// HTTP request header object - /// HTTP response header object - /// - public string RestGetRegionMethod(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) - { - return RestGetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse); - } - - /// - /// Performs a REST Set Operation - /// - /// - /// - /// - /// HTTP request header object - /// HTTP response header object - /// - public string RestSetRegionMethod(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) - { - return RestSetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse); - } - - /// - /// Returns information about a sim via a REST Request - /// - /// - /// - /// A string representing the sim's UUID - /// HTTP request header object - /// HTTP response header object - /// Information about the sim in XML - public string RestGetSimMethod(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) - { - string respstring = String.Empty; - - RegionProfileData TheSim; - - UUID UUID; - if (UUID.TryParse(param, out UUID)) - { - TheSim = GetRegion(UUID); - - if (!(TheSim == null)) - { - respstring = ""; - respstring += "" + TheSim.regionSendKey + ""; - respstring += ""; - respstring += "" + TheSim.UUID.ToString() + ""; - respstring += "" + TheSim.regionName + ""; - respstring += "" + TheSim.serverIP + ""; - respstring += "" + TheSim.serverPort.ToString() + ""; - respstring += "" + TheSim.regionLocX.ToString() + ""; - respstring += "" + TheSim.regionLocY.ToString() + ""; - respstring += "1"; - respstring += ""; - respstring += ""; - } - } - else - { - respstring = ""; - respstring += "Param must be a UUID"; - respstring += ""; - } - - return respstring; - } - - /// - /// Creates or updates a sim via a REST Method Request - /// BROKEN with SQL Update - /// - /// - /// - /// - /// HTTP request header object - /// HTTP response header object - /// "OK" or an error - public string RestSetSimMethod(string request, string path, string param, - OSHttpRequest httpRequest, OSHttpResponse httpResponse) - { - Console.WriteLine("Processing region update via REST method"); - RegionProfileData theSim; - theSim = GetRegion(new UUID(param)); - if (theSim == null) - { - theSim = new RegionProfileData(); - UUID UUID = new UUID(param); - theSim.UUID = UUID; - theSim.regionRecvKey = Config.SimRecvKey; - } - - XmlDocument doc = new XmlDocument(); - doc.LoadXml(request); - XmlNode rootnode = doc.FirstChild; - XmlNode authkeynode = rootnode.ChildNodes[0]; - if (authkeynode.Name != "authkey") - { - return "ERROR! bad XML - expected authkey tag"; - } - - XmlNode simnode = rootnode.ChildNodes[1]; - if (simnode.Name != "sim") - { - return "ERROR! bad XML - expected sim tag"; - } - - //theSim.regionSendKey = Cfg; - theSim.regionRecvKey = Config.SimRecvKey; - theSim.regionSendKey = Config.SimSendKey; - theSim.regionSecret = Config.SimRecvKey; - theSim.regionDataURI = String.Empty; - theSim.regionAssetURI = Config.DefaultAssetServer; - theSim.regionAssetRecvKey = Config.AssetRecvKey; - theSim.regionAssetSendKey = Config.AssetSendKey; - theSim.regionUserURI = Config.DefaultUserServer; - theSim.regionUserSendKey = Config.UserSendKey; - theSim.regionUserRecvKey = Config.UserRecvKey; - - for (int i = 0; i < simnode.ChildNodes.Count; i++) - { - switch (simnode.ChildNodes[i].Name) - { - case "regionname": - theSim.regionName = simnode.ChildNodes[i].InnerText; - break; - - case "sim_ip": - theSim.serverIP = simnode.ChildNodes[i].InnerText; - break; - - case "sim_port": - theSim.serverPort = Convert.ToUInt32(simnode.ChildNodes[i].InnerText); - break; - - case "region_locx": - theSim.regionLocX = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText); - theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize)); - break; - - case "region_locy": - theSim.regionLocY = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText); - theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize)); - break; - } - } - - theSim.serverURI = "http://" + theSim.serverIP + ":" + theSim.serverPort + "/"; - bool requirePublic = false; - bool requireValid = true; - - if (requirePublic && - (theSim.serverIP.StartsWith("172.16") || theSim.serverIP.StartsWith("192.168") || - theSim.serverIP.StartsWith("10.") || theSim.serverIP.StartsWith("0.") || - theSim.serverIP.StartsWith("255."))) - { - return "ERROR! Servers must register with public addresses."; - } - - if (requireValid && (theSim.serverIP.StartsWith("0.") || theSim.serverIP.StartsWith("255."))) - { - return "ERROR! 0.*.*.* / 255.*.*.* Addresses are invalid, please check your server config and try again"; - } - - try - { - m_log.Info("[DATA]: " + - "Updating / adding via " + _plugins.Count + " storage provider(s) registered."); - - foreach (IGridDataPlugin plugin in _plugins) - { - try - { - //Check reservations - ReservationData reserveData = - plugin.GetReservationAtPoint(theSim.regionLocX, theSim.regionLocY); - if ((reserveData != null && reserveData.gridRecvKey == theSim.regionRecvKey) || - (reserveData == null && authkeynode.InnerText != theSim.regionRecvKey)) - { - plugin.AddProfile(theSim); - m_log.Info("[grid]: New sim added to grid (" + theSim.regionName + ")"); - logToDB(theSim.ToString(), "RestSetSimMethod", String.Empty, 5, - "Region successfully updated and connected to grid."); - } - else - { - m_log.Warn("[grid]: " + - "Unable to update region (RestSetSimMethod): Incorrect reservation auth key."); - // Wanted: " + reserveData.gridRecvKey + ", Got: " + theSim.regionRecvKey + "."); - return "Unable to update region (RestSetSimMethod): Incorrect auth key."; - } - } - catch (Exception e) - { - m_log.Warn("[GRID]: GetRegionPlugin Handle " + plugin.Name + " unable to add new sim: " + - e.ToString()); - } - } - return "OK"; - } - catch (Exception e) - { - return "ERROR! Could not save to database! (" + e.ToString() + ")"; - } - } - - public XmlRpcResponse XmlRPCRegisterMessageServer(XmlRpcRequest request) - { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable requestData = (Hashtable)request.Params[0]; - Hashtable responseData = new Hashtable(); - - if (requestData.Contains("uri")) - { - string URI = (string)requestData["URI"]; - string sendkey = (string)requestData["sendkey"]; - string recvkey = (string)requestData["recvkey"]; - MessageServerInfo m = new MessageServerInfo(); - m.URI = URI; - m.sendkey = sendkey; - m.recvkey = recvkey; - if (!_MessageServers.Contains(m)) - _MessageServers.Add(m); - responseData["responsestring"] = "TRUE"; - response.Value = responseData; - } - return response; - } - - public XmlRpcResponse XmlRPCDeRegisterMessageServer(XmlRpcRequest request) - { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable requestData = (Hashtable)request.Params[0]; - Hashtable responseData = new Hashtable(); - - if (requestData.Contains("uri")) - { - string URI = (string)requestData["uri"]; - string sendkey = (string)requestData["sendkey"]; - string recvkey = (string)requestData["recvkey"]; - MessageServerInfo m = new MessageServerInfo(); - m.URI = URI; - m.sendkey = sendkey; - m.recvkey = recvkey; - if (_MessageServers.Contains(m)) - _MessageServers.Remove(m); - responseData["responsestring"] = "TRUE"; - response.Value = responseData; - } - return response; - } - - /// - /// Construct an XMLRPC registration disabled response - /// - /// - /// - public static XmlRpcResponse XmlRPCRegionRegistrationDisabledResponse(string error) - { - XmlRpcResponse errorResponse = new XmlRpcResponse(); - Hashtable errorResponseData = new Hashtable(); - errorResponse.Value = errorResponseData; - errorResponseData["restricted"] = error; - return errorResponse; - } - } - - /// - /// Exception generated when a simulator fails to login to the grid - /// - public class LoginException : Exception - { - /// - /// Return an XmlRpcResponse version of the exception message suitable for sending to a client - /// - /// - /// - public XmlRpcResponse XmlRpcErrorResponse - { - get { return m_xmlRpcErrorResponse; } - } - private XmlRpcResponse m_xmlRpcErrorResponse; - - public LoginException(string message, string xmlRpcMessage) : base(message) - { - // FIXME: Might be neater to refactor and put the method inside here - m_xmlRpcErrorResponse = GridManager.ErrorResponse(xmlRpcMessage); - } - - public LoginException(string message, string xmlRpcMessage, Exception e) : base(message, e) - { - // FIXME: Might be neater to refactor and put the method inside here - m_xmlRpcErrorResponse = GridManager.ErrorResponse(xmlRpcMessage); - } - } -} diff --git a/OpenSim/Grid/GridServer/GridMessagingModule.cs b/OpenSim/Grid/GridServer/GridMessagingModule.cs new file mode 100644 index 0000000..348e56c --- /dev/null +++ b/OpenSim/Grid/GridServer/GridMessagingModule.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Nwc.XmlRpc; +using log4net; +using OpenSim.Framework.Servers; +using OpenSim.Framework; + +namespace OpenSim.Grid.GridServer +{ + public class GridMessagingModule : IGridMessagingModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected GridDBService m_gridDBService; + protected IGridCore m_gridCore; + + protected GridConfig m_config; + + /// + /// Used to notify old regions as to which OpenSim version to upgrade to + /// + private string m_opensimVersion; + + protected BaseHttpServer m_httpServer; + + // This is here so that the grid server can hand out MessageServer settings to regions on registration + private List _MessageServers = new List(); + + public List MessageServers + { + get { return _MessageServers; } + } + + public GridMessagingModule(string opensimVersion, GridDBService gridDBService, IGridCore gridCore, GridConfig config) + { + m_opensimVersion = opensimVersion; + m_gridDBService = gridDBService; + m_gridCore = gridCore; + m_config = config; + m_httpServer = m_gridCore.GetHttpServer(); + } + + public void Initialise() + { + m_gridCore.RegisterInterface(this); + // Message Server ---> Grid Server + m_httpServer.AddXmlRPCHandler("register_messageserver", XmlRPCRegisterMessageServer); + m_httpServer.AddXmlRPCHandler("deregister_messageserver", XmlRPCDeRegisterMessageServer); + + } + + public XmlRpcResponse XmlRPCRegisterMessageServer(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + + if (requestData.Contains("uri")) + { + string URI = (string)requestData["URI"]; + string sendkey = (string)requestData["sendkey"]; + string recvkey = (string)requestData["recvkey"]; + MessageServerInfo m = new MessageServerInfo(); + m.URI = URI; + m.sendkey = sendkey; + m.recvkey = recvkey; + if (!_MessageServers.Contains(m)) + _MessageServers.Add(m); + responseData["responsestring"] = "TRUE"; + response.Value = responseData; + } + return response; + } + + public XmlRpcResponse XmlRPCDeRegisterMessageServer(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + + if (requestData.Contains("uri")) + { + string URI = (string)requestData["uri"]; + string sendkey = (string)requestData["sendkey"]; + string recvkey = (string)requestData["recvkey"]; + MessageServerInfo m = new MessageServerInfo(); + m.URI = URI; + m.sendkey = sendkey; + m.recvkey = recvkey; + if (_MessageServers.Contains(m)) + _MessageServers.Remove(m); + responseData["responsestring"] = "TRUE"; + response.Value = responseData; + } + return response; + } + } +} diff --git a/OpenSim/Grid/GridServer/GridRestModule.cs b/OpenSim/Grid/GridServer/GridRestModule.cs new file mode 100644 index 0000000..1ed0ac1 --- /dev/null +++ b/OpenSim/Grid/GridServer/GridRestModule.cs @@ -0,0 +1,269 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; +using log4net; +using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Servers; + +namespace OpenSim.Grid.GridServer +{ + public class GridRestModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private GridDBService m_gridDBService; + private IGridCore m_gridCore; + + protected GridConfig m_config; + + /// + /// Used to notify old regions as to which OpenSim version to upgrade to + /// + private string m_opensimVersion; + + protected BaseHttpServer m_httpServer; + + /// + /// Constructor + /// + /// + /// Used to notify old regions as to which OpenSim version to upgrade to + /// + public GridRestModule(string opensimVersion, GridDBService gridDBService, IGridCore gridCore, GridConfig config) + { + m_opensimVersion = opensimVersion; + m_gridDBService = gridDBService; + m_gridCore = gridCore; + m_config = config; + m_httpServer = m_gridCore.GetHttpServer(); + } + + public void Initialise() + { + m_httpServer.AddStreamHandler(new RestStreamHandler("GET", "/sims/", RestGetSimMethod)); + m_httpServer.AddStreamHandler(new RestStreamHandler("POST", "/sims/", RestSetSimMethod)); + + m_httpServer.AddStreamHandler(new RestStreamHandler("GET", "/regions/", RestGetRegionMethod)); + m_httpServer.AddStreamHandler(new RestStreamHandler("POST", "/regions/", RestSetRegionMethod)); + } + + /// + /// Performs a REST Get Operation + /// + /// + /// + /// + /// HTTP request header object + /// HTTP response header object + /// + public string RestGetRegionMethod(string request, string path, string param, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return RestGetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse); + } + + /// + /// Performs a REST Set Operation + /// + /// + /// + /// + /// HTTP request header object + /// HTTP response header object + /// + public string RestSetRegionMethod(string request, string path, string param, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return RestSetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse); + } + + /// + /// Returns information about a sim via a REST Request + /// + /// + /// + /// A string representing the sim's UUID + /// HTTP request header object + /// HTTP response header object + /// Information about the sim in XML + public string RestGetSimMethod(string request, string path, string param, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + string respstring = String.Empty; + + RegionProfileData TheSim; + + UUID UUID; + if (UUID.TryParse(param, out UUID)) + { + TheSim = m_gridDBService.GetRegion(UUID); + + if (!(TheSim == null)) + { + respstring = ""; + respstring += "" + TheSim.regionSendKey + ""; + respstring += ""; + respstring += "" + TheSim.UUID.ToString() + ""; + respstring += "" + TheSim.regionName + ""; + respstring += "" + TheSim.serverIP + ""; + respstring += "" + TheSim.serverPort.ToString() + ""; + respstring += "" + TheSim.regionLocX.ToString() + ""; + respstring += "" + TheSim.regionLocY.ToString() + ""; + respstring += "1"; + respstring += ""; + respstring += ""; + } + } + else + { + respstring = ""; + respstring += "Param must be a UUID"; + respstring += ""; + } + + return respstring; + } + + /// + /// Creates or updates a sim via a REST Method Request + /// BROKEN with SQL Update + /// + /// + /// + /// + /// HTTP request header object + /// HTTP response header object + /// "OK" or an error + public string RestSetSimMethod(string request, string path, string param, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + Console.WriteLine("Processing region update via REST method"); + RegionProfileData theSim; + theSim = m_gridDBService.GetRegion(new UUID(param)); + if (theSim == null) + { + theSim = new RegionProfileData(); + UUID UUID = new UUID(param); + theSim.UUID = UUID; + theSim.regionRecvKey = m_config.SimRecvKey; + } + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(request); + XmlNode rootnode = doc.FirstChild; + XmlNode authkeynode = rootnode.ChildNodes[0]; + if (authkeynode.Name != "authkey") + { + return "ERROR! bad XML - expected authkey tag"; + } + + XmlNode simnode = rootnode.ChildNodes[1]; + if (simnode.Name != "sim") + { + return "ERROR! bad XML - expected sim tag"; + } + + //theSim.regionSendKey = Cfg; + theSim.regionRecvKey = m_config.SimRecvKey; + theSim.regionSendKey = m_config.SimSendKey; + theSim.regionSecret = m_config.SimRecvKey; + theSim.regionDataURI = String.Empty; + theSim.regionAssetURI = m_config.DefaultAssetServer; + theSim.regionAssetRecvKey = m_config.AssetRecvKey; + theSim.regionAssetSendKey = m_config.AssetSendKey; + theSim.regionUserURI = m_config.DefaultUserServer; + theSim.regionUserSendKey = m_config.UserSendKey; + theSim.regionUserRecvKey = m_config.UserRecvKey; + + for (int i = 0; i < simnode.ChildNodes.Count; i++) + { + switch (simnode.ChildNodes[i].Name) + { + case "regionname": + theSim.regionName = simnode.ChildNodes[i].InnerText; + break; + + case "sim_ip": + theSim.serverIP = simnode.ChildNodes[i].InnerText; + break; + + case "sim_port": + theSim.serverPort = Convert.ToUInt32(simnode.ChildNodes[i].InnerText); + break; + + case "region_locx": + theSim.regionLocX = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText); + theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize)); + break; + + case "region_locy": + theSim.regionLocY = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText); + theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize)); + break; + } + } + + theSim.serverURI = "http://" + theSim.serverIP + ":" + theSim.serverPort + "/"; + bool requirePublic = false; + bool requireValid = true; + + if (requirePublic && + (theSim.serverIP.StartsWith("172.16") || theSim.serverIP.StartsWith("192.168") || + theSim.serverIP.StartsWith("10.") || theSim.serverIP.StartsWith("0.") || + theSim.serverIP.StartsWith("255."))) + { + return "ERROR! Servers must register with public addresses."; + } + + if (requireValid && (theSim.serverIP.StartsWith("0.") || theSim.serverIP.StartsWith("255."))) + { + return "ERROR! 0.*.*.* / 255.*.*.* Addresses are invalid, please check your server config and try again"; + } + + try + { + m_log.Info("[DATA]: " + + "Updating / adding via " + m_gridDBService.GetNumberOfPlugins() + " storage provider(s) registered."); + + return m_gridDBService.CheckReservations(theSim, authkeynode); + } + catch (Exception e) + { + return "ERROR! Could not save to database! (" + e.ToString() + ")"; + } + } + } +} diff --git a/OpenSim/Grid/GridServer/GridServerBase.cs b/OpenSim/Grid/GridServer/GridServerBase.cs index bcd1403..d4d268c 100644 --- a/OpenSim/Grid/GridServer/GridServerBase.cs +++ b/OpenSim/Grid/GridServer/GridServerBase.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; using System.IO; using System.Reflection; @@ -38,12 +39,18 @@ namespace OpenSim.Grid.GridServer { /// /// - public class GridServerBase : BaseOpenSimServer + public class GridServerBase : BaseOpenSimServer, IGridCore { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected GridConfig m_config; - protected GridManager m_gridManager; + + protected GridXmlRpcModule m_gridXmlRpcModule; + protected GridMessagingModule m_gridMessageModule; + protected GridRestModule m_gridRestModule; + + protected GridDBService m_gridDBService; + protected List m_plugins = new List(); public void Work() @@ -66,14 +73,14 @@ namespace OpenSim.Grid.GridServer { switch (cmd[0]) { - case "enable": - m_config.AllowRegionRegistration = true; - m_log.Info("Region registration enabled"); - break; - case "disable": - m_config.AllowRegionRegistration = false; - m_log.Info("Region registration disabled"); - break; + case "enable": + m_config.AllowRegionRegistration = true; + m_log.Info("Region registration enabled"); + break; + case "disable": + m_config.AllowRegionRegistration = false; + m_log.Info("Region registration disabled"); + break; } } @@ -84,32 +91,32 @@ namespace OpenSim.Grid.GridServer m_log.Info("Region registration enabled."); } else - { + { m_log.Info("Region registration disabled."); } } - + protected override void StartupSpecific() { m_config = new GridConfig("GRID SERVER", (Path.Combine(Util.configDir(), "GridServer_Config.xml"))); - SetupGridManager(); - m_log.Info("[GRID]: Starting HTTP process"); m_httpServer = new BaseHttpServer(m_config.HttpPort); + SetupGridServices(); + AddHttpHandlers(); LoadPlugins(); m_httpServer.Start(); -// m_log.Info("[GRID]: Starting sim status checker"); -// -// Timer simCheckTimer = new Timer(3600000 * 3); // 3 Hours between updates. -// simCheckTimer.Elapsed += new ElapsedEventHandler(CheckSims); -// simCheckTimer.Enabled = true; + // m_log.Info("[GRID]: Starting sim status checker"); + // + // Timer simCheckTimer = new Timer(3600000 * 3); // 3 Hours between updates. + // simCheckTimer.Elapsed += new ElapsedEventHandler(CheckSims); + // simCheckTimer.Enabled = true; base.StartupSpecific(); @@ -130,38 +137,32 @@ namespace OpenSim.Grid.GridServer protected void AddHttpHandlers() { - m_httpServer.AddXmlRPCHandler("simulator_login", m_gridManager.XmlRpcSimulatorLoginMethod); - m_httpServer.AddXmlRPCHandler("simulator_data_request", m_gridManager.XmlRpcSimulatorDataRequestMethod); - m_httpServer.AddXmlRPCHandler("simulator_after_region_moved", m_gridManager.XmlRpcDeleteRegionMethod); - m_httpServer.AddXmlRPCHandler("map_block", m_gridManager.XmlRpcMapBlockMethod); - m_httpServer.AddXmlRPCHandler("search_for_region_by_name", m_gridManager.XmlRpcSearchForRegionMethod); - - // Message Server ---> Grid Server - m_httpServer.AddXmlRPCHandler("register_messageserver", m_gridManager.XmlRPCRegisterMessageServer); - m_httpServer.AddXmlRPCHandler("deregister_messageserver", m_gridManager.XmlRPCDeRegisterMessageServer); - - m_httpServer.AddStreamHandler(new RestStreamHandler("GET", "/sims/", m_gridManager.RestGetSimMethod)); - m_httpServer.AddStreamHandler(new RestStreamHandler("POST", "/sims/", m_gridManager.RestSetSimMethod)); - - m_httpServer.AddStreamHandler(new RestStreamHandler("GET", "/regions/", m_gridManager.RestGetRegionMethod)); - m_httpServer.AddStreamHandler(new RestStreamHandler("POST", "/regions/", m_gridManager.RestSetRegionMethod)); + // Registering Handlers is now done in the components/modules } protected void LoadPlugins() { - PluginLoader loader = - new PluginLoader (new GridPluginInitialiser (this)); + PluginLoader loader = + new PluginLoader(new GridPluginInitialiser(this)); - loader.Load ("/OpenSim/GridServer"); + loader.Load("/OpenSim/GridServer"); m_plugins = loader.Plugins; } - protected virtual void SetupGridManager() + protected virtual void SetupGridServices() { m_log.Info("[DATA]: Connecting to Storage Server"); - m_gridManager = new GridManager(m_version); - m_gridManager.AddPlugin(m_config.DatabaseProvider, m_config.DatabaseConnect); - m_gridManager.Config = m_config; + m_gridDBService = new GridDBService(); + m_gridDBService.AddPlugin(m_config.DatabaseProvider, m_config.DatabaseConnect); + + m_gridMessageModule = new GridMessagingModule(m_version, m_gridDBService, this, m_config); + m_gridMessageModule.Initialise(); + + m_gridXmlRpcModule = new GridXmlRpcModule(m_version, m_gridDBService, this, m_config); + m_gridXmlRpcModule.Initialise(); + + m_gridRestModule = new GridRestModule(m_version, m_gridDBService, this, m_config); + m_gridRestModule.Initialise(); } public void CheckSims(object sender, ElapsedEventArgs e) @@ -205,5 +206,43 @@ namespace OpenSim.Grid.GridServer { foreach (IGridPlugin plugin in m_plugins) plugin.Dispose(); } + + #region IGridCore + private readonly Dictionary m_gridInterfaces = new Dictionary(); + + /// + /// Register an interface on this client, should only be called in the constructor. + /// + /// + /// + public void RegisterInterface(T iface) + { + lock (m_gridInterfaces) + { + m_gridInterfaces.Add(typeof(T), iface); + } + } + + public bool TryGet(out T iface) + { + if (m_gridInterfaces.ContainsKey(typeof(T))) + { + iface = (T)m_gridInterfaces[typeof(T)]; + return true; + } + iface = default(T); + return false; + } + + public T Get() + { + return (T)m_gridInterfaces[typeof(T)]; + } + + public BaseHttpServer GetHttpServer() + { + return m_httpServer; + } + #endregion } } diff --git a/OpenSim/Grid/GridServer/GridXmlRpcModule.cs b/OpenSim/Grid/GridServer/GridXmlRpcModule.cs new file mode 100644 index 0000000..0eb7d1f --- /dev/null +++ b/OpenSim/Grid/GridServer/GridXmlRpcModule.cs @@ -0,0 +1,844 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; +using log4net; +using Nwc.XmlRpc; +using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Servers; + +namespace OpenSim.Grid.GridServer +{ + public class GridXmlRpcModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private GridDBService m_gridDBService; + private IGridCore m_gridCore; + + protected GridConfig m_config; + + /// + /// Used to notify old regions as to which OpenSim version to upgrade to + /// + private string m_opensimVersion; + + protected BaseHttpServer m_httpServer; + + /// + /// Constructor + /// + /// + /// Used to notify old regions as to which OpenSim version to upgrade to + /// + public GridXmlRpcModule(string opensimVersion, GridDBService gridDBService, IGridCore gridCore, GridConfig config) + { + m_opensimVersion = opensimVersion; + m_gridDBService = gridDBService; + m_gridCore = gridCore; + m_config = config; + m_httpServer = m_gridCore.GetHttpServer(); + } + + public void Initialise() + { + m_httpServer.AddXmlRPCHandler("simulator_login", XmlRpcSimulatorLoginMethod); + m_httpServer.AddXmlRPCHandler("simulator_data_request", XmlRpcSimulatorDataRequestMethod); + m_httpServer.AddXmlRPCHandler("simulator_after_region_moved", XmlRpcDeleteRegionMethod); + m_httpServer.AddXmlRPCHandler("map_block", XmlRpcMapBlockMethod); + m_httpServer.AddXmlRPCHandler("search_for_region_by_name", XmlRpcSearchForRegionMethod); + } + + /// + /// Returns a XML String containing a list of the neighbouring regions + /// + /// The regionhandle for the center sim + /// An XML string containing neighbour entities + public string GetXMLNeighbours(ulong reqhandle) + { + string response = String.Empty; + RegionProfileData central_region = m_gridDBService.GetRegion(reqhandle); + RegionProfileData neighbour; + for (int x = -1; x < 2; x++) + { + for (int y = -1; y < 2; y++) + { + if ( + m_gridDBService.GetRegion( + Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), + (uint)(central_region.regionLocY + y) * Constants.RegionSize)) != null) + { + neighbour = + m_gridDBService.GetRegion( + Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), + (uint)(central_region.regionLocY + y) * Constants.RegionSize)); + + response += ""; + response += "" + neighbour.serverIP + ""; + response += "" + neighbour.serverPort.ToString() + ""; + response += "" + neighbour.regionLocX.ToString() + ""; + response += "" + neighbour.regionLocY.ToString() + ""; + response += "" + neighbour.regionHandle.ToString() + ""; + response += ""; + } + } + } + return response; + } + + /// + /// Checks that it's valid to replace the existing region data with new data + /// + /// Currently, this means ensure that the keys passed in by the new region + /// match those in the original region. (XXX Is this correct? Shouldn't we simply check + /// against the keys in the current configuration?) + /// + /// + /// + protected virtual void ValidateOverwriteKeys(RegionProfileData sim, RegionProfileData existingSim) + { + if (!(existingSim.regionRecvKey == sim.regionRecvKey && existingSim.regionSendKey == sim.regionSendKey)) + { + throw new LoginException( + String.Format( + "Authentication failed when trying to login existing region {0} at location {1} {2} currently occupied by {3}" + + " with the region's send key {4} (expected {5}) and the region's receive key {6} (expected {7})", + sim.regionName, sim.regionLocX, sim.regionLocY, existingSim.regionName, + sim.regionSendKey, existingSim.regionSendKey, sim.regionRecvKey, existingSim.regionRecvKey), + "The keys required to login your region did not match the grid server keys. Please check your grid send and receive keys."); + } + } + + /// + /// Checks that the new region data is valid. + /// + /// Currently, this means checking that the keys passed in by the new region + /// match those in the grid server's configuration. + /// + /// + /// + /// Thrown if region login failed + protected virtual void ValidateNewRegionKeys(RegionProfileData sim) + { + if (!(sim.regionRecvKey == m_config.SimSendKey && sim.regionSendKey == m_config.SimRecvKey)) + { + throw new LoginException( + String.Format( + "Authentication failed when trying to login new region {0} at location {1} {2}" + + " with the region's send key {3} (expected {4}) and the region's receive key {5} (expected {6})", + sim.regionName, sim.regionLocX, sim.regionLocY, + sim.regionSendKey, m_config.SimRecvKey, sim.regionRecvKey, m_config.SimSendKey), + "The keys required to login your region did not match your existing region keys. Please check your grid send and receive keys."); + } + } + + /// + /// Check that a region's http uri is externally contactable. + /// + /// + /// Thrown if the region is not contactable + protected virtual void ValidateRegionContactable(RegionProfileData sim) + { + string regionStatusUrl = String.Format("{0}{1}", sim.httpServerURI, "simstatus/"); + string regionStatusResponse; + + RestClient rc = new RestClient(regionStatusUrl); + rc.RequestMethod = "GET"; + + m_log.DebugFormat("[LOGIN]: Contacting {0} for status of region {1}", regionStatusUrl, sim.regionName); + + try + { + Stream rs = rc.Request(); + StreamReader sr = new StreamReader(rs); + regionStatusResponse = sr.ReadToEnd(); + sr.Close(); + } + catch (Exception e) + { + throw new LoginException( + String.Format("Region status request to {0} failed", regionStatusUrl), + String.Format( + "The grid service could not contact the http url {0} at your region. Please make sure this url is reachable by the grid service", + regionStatusUrl), + e); + } + + if (!regionStatusResponse.Equals("OK")) + { + throw new LoginException( + String.Format( + "Region {0} at {1} returned status response {2} rather than {3}", + sim.regionName, regionStatusUrl, regionStatusResponse, "OK"), + String.Format( + "When the grid service asked for the status of your region, it received the response {0} rather than {1}. Please check your status", + regionStatusResponse, "OK")); + } + } + + /// + /// Construct an XMLRPC error response + /// + /// + /// + public static XmlRpcResponse ErrorResponse(string error) + { + XmlRpcResponse errorResponse = new XmlRpcResponse(); + Hashtable errorResponseData = new Hashtable(); + errorResponse.Value = errorResponseData; + errorResponseData["error"] = error; + return errorResponse; + } + + /// + /// Performed when a region connects to the grid server initially. + /// + /// The XML RPC Request + /// Startup parameters + public XmlRpcResponse XmlRpcSimulatorLoginMethod(XmlRpcRequest request) + { + RegionProfileData sim; + RegionProfileData existingSim; + + Hashtable requestData = (Hashtable)request.Params[0]; + UUID uuid; + + if (!requestData.ContainsKey("UUID") || !UUID.TryParse((string)requestData["UUID"], out uuid)) + { + m_log.Debug("[LOGIN PRELUDE]: Region connected without a UUID, sending back error response."); + return ErrorResponse("No UUID passed to grid server - unable to connect you"); + } + + try + { + sim = RegionFromRequest(requestData); + } + catch (FormatException e) + { + m_log.Debug("[LOGIN PRELUDE]: Invalid login parameters, sending back error response."); + return ErrorResponse("Wrong format in login parameters. Please verify parameters." + e.ToString()); + } + + m_log.InfoFormat("[LOGIN BEGIN]: Received login request from simulator: {0}", sim.regionName); + + if (!m_config.AllowRegionRegistration) + { + m_log.DebugFormat( + "[LOGIN END]: Disabled region registration blocked login request from simulator: {0}", + sim.regionName); + + return ErrorResponse("This grid is currently not accepting region registrations."); + } + + int majorInterfaceVersion = 0; + if (requestData.ContainsKey("major_interface_version")) + int.TryParse((string)requestData["major_interface_version"], out majorInterfaceVersion); + + if (majorInterfaceVersion != VersionInfo.MajorInterfaceVersion) + { + return ErrorResponse( + String.Format( + "Your region service implements OGS1 interface version {0}" + + " but this grid requires that the region implement OGS1 interface version {1} to connect." + + " Try changing to OpenSimulator {2}", + majorInterfaceVersion, VersionInfo.MajorInterfaceVersion, m_opensimVersion)); + } + + existingSim = m_gridDBService.GetRegion(sim.regionHandle); + + if (existingSim == null || existingSim.UUID == sim.UUID || sim.UUID != sim.originUUID) + { + try + { + if (existingSim == null) + { + ValidateNewRegionKeys(sim); + } + else + { + ValidateOverwriteKeys(sim, existingSim); + } + + ValidateRegionContactable(sim); + } + catch (LoginException e) + { + string logMsg = e.Message; + if (e.InnerException != null) + logMsg += ", " + e.InnerException.Message; + + m_log.WarnFormat("[LOGIN END]: {0}", logMsg); + + return e.XmlRpcErrorResponse; + } + + m_gridDBService.LoginRegion(sim, existingSim); + + XmlRpcResponse response = CreateLoginResponse(sim); + + return response; + } + else + { + m_log.Warn("[LOGIN END]: Failed to login region " + sim.regionName + " at location " + sim.regionLocX + " " + sim.regionLocY + " currently occupied by " + existingSim.regionName); + return ErrorResponse("Another region already exists at that location. Please try another."); + } + } + + /// + /// Construct a successful response to a simulator's login attempt. + /// + /// + /// + private XmlRpcResponse CreateLoginResponse(RegionProfileData sim) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + response.Value = responseData; + + ArrayList SimNeighboursData = GetSimNeighboursData(sim); + + responseData["UUID"] = sim.UUID.ToString(); + responseData["region_locx"] = sim.regionLocX.ToString(); + responseData["region_locy"] = sim.regionLocY.ToString(); + responseData["regionname"] = sim.regionName; + responseData["estate_id"] = "1"; + responseData["neighbours"] = SimNeighboursData; + + responseData["sim_ip"] = sim.serverIP; + responseData["sim_port"] = sim.serverPort.ToString(); + responseData["asset_url"] = sim.regionAssetURI; + responseData["asset_sendkey"] = sim.regionAssetSendKey; + responseData["asset_recvkey"] = sim.regionAssetRecvKey; + responseData["user_url"] = sim.regionUserURI; + responseData["user_sendkey"] = sim.regionUserSendKey; + responseData["user_recvkey"] = sim.regionUserRecvKey; + responseData["authkey"] = sim.regionSecret; + + // New! If set, use as URL to local sim storage (ie http://remotehost/region.Yap) + responseData["data_uri"] = sim.regionDataURI; + + responseData["allow_forceful_banlines"] = m_config.AllowForcefulBanlines; + + // Instead of sending a multitude of message servers to the registering sim + // we should probably be sending a single one and parhaps it's backup + // that has responsibility over routing it's messages. + + // The Sim won't be contacting us again about any of the message server stuff during it's time up. + + responseData["messageserver_count"] = 0; + + IGridMessagingModule messagingModule; + if (m_gridCore.TryGet(out messagingModule)) + { + List messageServers = messagingModule.MessageServers; + responseData["messageserver_count"] = messageServers.Count; + + for (int i = 0; i < messageServers.Count; i++) + { + responseData["messageserver_uri" + i] = messageServers[i].URI; + responseData["messageserver_sendkey" + i] = messageServers[i].sendkey; + responseData["messageserver_recvkey" + i] = messageServers[i].recvkey; + } + } + return response; + } + + private ArrayList GetSimNeighboursData(RegionProfileData sim) + { + ArrayList SimNeighboursData = new ArrayList(); + + RegionProfileData neighbour; + Hashtable NeighbourBlock; + + //First use the fast method. (not implemented in SQLLite) + List neighbours = m_gridDBService.GetRegions(sim.regionLocX - 1, sim.regionLocY - 1, sim.regionLocX + 1, sim.regionLocY + 1); + + if (neighbours.Count > 0) + { + foreach (RegionProfileData aSim in neighbours) + { + NeighbourBlock = new Hashtable(); + NeighbourBlock["sim_ip"] = aSim.serverIP; + NeighbourBlock["sim_port"] = aSim.serverPort.ToString(); + NeighbourBlock["region_locx"] = aSim.regionLocX.ToString(); + NeighbourBlock["region_locy"] = aSim.regionLocY.ToString(); + NeighbourBlock["UUID"] = aSim.ToString(); + NeighbourBlock["regionHandle"] = aSim.regionHandle.ToString(); + + if (aSim.UUID != sim.UUID) + { + SimNeighboursData.Add(NeighbourBlock); + } + } + } + else + { + for (int x = -1; x < 2; x++) + { + for (int y = -1; y < 2; y++) + { + if ( + m_gridDBService.GetRegion( + Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), + (uint)(sim.regionLocY + y) * Constants.RegionSize)) != null) + { + neighbour = + m_gridDBService.GetRegion( + Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), + (uint)(sim.regionLocY + y) * Constants.RegionSize)); + + NeighbourBlock = new Hashtable(); + NeighbourBlock["sim_ip"] = neighbour.serverIP; + NeighbourBlock["sim_port"] = neighbour.serverPort.ToString(); + NeighbourBlock["region_locx"] = neighbour.regionLocX.ToString(); + NeighbourBlock["region_locy"] = neighbour.regionLocY.ToString(); + NeighbourBlock["UUID"] = neighbour.UUID.ToString(); + NeighbourBlock["regionHandle"] = neighbour.regionHandle.ToString(); + + if (neighbour.UUID != sim.UUID) SimNeighboursData.Add(NeighbourBlock); + } + } + } + } + return SimNeighboursData; + } + + /// + /// Loads the grid's own RegionProfileData object with data from the XMLRPC simulator_login request from a region + /// + /// + /// + private RegionProfileData RegionFromRequest(Hashtable requestData) + { + RegionProfileData sim; + sim = new RegionProfileData(); + + sim.UUID = new UUID((string)requestData["UUID"]); + sim.originUUID = new UUID((string)requestData["originUUID"]); + + sim.regionRecvKey = String.Empty; + sim.regionSendKey = String.Empty; + + if (requestData.ContainsKey("region_secret")) + { + string regionsecret = (string)requestData["region_secret"]; + if (regionsecret.Length > 0) + sim.regionSecret = regionsecret; + else + sim.regionSecret = m_config.SimRecvKey; + + } + else + { + sim.regionSecret = m_config.SimRecvKey; + } + + sim.regionDataURI = String.Empty; + sim.regionAssetURI = m_config.DefaultAssetServer; + sim.regionAssetRecvKey = m_config.AssetRecvKey; + sim.regionAssetSendKey = m_config.AssetSendKey; + sim.regionUserURI = m_config.DefaultUserServer; + sim.regionUserSendKey = m_config.UserSendKey; + sim.regionUserRecvKey = m_config.UserRecvKey; + + sim.serverIP = (string)requestData["sim_ip"]; + sim.serverPort = Convert.ToUInt32((string)requestData["sim_port"]); + sim.httpPort = Convert.ToUInt32((string)requestData["http_port"]); + sim.remotingPort = Convert.ToUInt32((string)requestData["remoting_port"]); + sim.regionLocX = Convert.ToUInt32((string)requestData["region_locx"]); + sim.regionLocY = Convert.ToUInt32((string)requestData["region_locy"]); + sim.regionLocZ = 0; + + UUID textureID; + if (UUID.TryParse((string)requestData["map-image-id"], out textureID)) + { + sim.regionMapTextureID = textureID; + } + + // part of an initial brutish effort to provide accurate information (as per the xml region spec) + // wrt the ownership of a given region + // the (very bad) assumption is that this value is being read and handled inconsistently or + // not at all. Current strategy is to put the code in place to support the validity of this information + // and to roll forward debugging any issues from that point + // + // this particular section of the mod attempts to receive a value from the region's xml file by way of + // OSG1GridServices for the region's owner + sim.owner_uuid = (UUID)(string)requestData["master_avatar_uuid"]; + + try + { + sim.regionRecvKey = (string)requestData["recvkey"]; + sim.regionSendKey = (string)requestData["authkey"]; + } + catch (KeyNotFoundException) { } + + sim.regionHandle = Utils.UIntsToLong((sim.regionLocX * Constants.RegionSize), (sim.regionLocY * Constants.RegionSize)); + sim.serverURI = (string)requestData["server_uri"]; + + sim.httpServerURI = "http://" + sim.serverIP + ":" + sim.httpPort + "/"; + + sim.regionName = (string)requestData["sim_name"]; + return sim; + } + + /// + /// Returns an XML RPC response to a simulator profile request + /// Performed after moving a region. + /// + /// + /// + /// The XMLRPC Request + /// Processing parameters + public XmlRpcResponse XmlRpcDeleteRegionMethod(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + response.Value = responseData; + + //RegionProfileData TheSim = null; + string uuid; + Hashtable requestData = (Hashtable)request.Params[0]; + + if (requestData.ContainsKey("UUID")) + { + //TheSim = GetRegion(new UUID((string) requestData["UUID"])); + uuid = requestData["UUID"].ToString(); + m_log.InfoFormat("[LOGOUT]: Logging out region: {0}", uuid); +// logToDB((new LLUUID((string)requestData["UUID"])).ToString(),"XmlRpcDeleteRegionMethod","", 5,"Attempting delete with UUID."); + } + else + { + responseData["error"] = "No UUID or region_handle passed to grid server - unable to delete"; + return response; + } + + DataResponse insertResponse = m_gridDBService.DeleteRegion(uuid); + + string insertResp = ""; + switch (insertResponse) + { + case DataResponse.RESPONSE_OK: + //MainLog.Instance.Verbose("grid", "Deleting region successful: " + uuid); + insertResp = "Deleting region successful: " + uuid; + break; + case DataResponse.RESPONSE_ERROR: + //MainLog.Instance.Warn("storage", "Deleting region failed (Error): " + uuid); + insertResp = "Deleting region failed (Error): " + uuid; + break; + case DataResponse.RESPONSE_INVALIDCREDENTIALS: + //MainLog.Instance.Warn("storage", "Deleting region failed (Invalid Credentials): " + uuid); + insertResp = "Deleting region (Invalid Credentials): " + uuid; + break; + case DataResponse.RESPONSE_AUTHREQUIRED: + //MainLog.Instance.Warn("storage", "Deleting region failed (Authentication Required): " + uuid); + insertResp = "Deleting region (Authentication Required): " + uuid; + break; + } + + responseData["status"] = insertResp; + + return response; + } + + /// + /// Returns an XML RPC response to a simulator profile request + /// + /// + /// + public XmlRpcResponse XmlRpcSimulatorDataRequestMethod(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable)request.Params[0]; + Hashtable responseData = new Hashtable(); + RegionProfileData simData = null; + if (requestData.ContainsKey("region_UUID")) + { + UUID regionID = new UUID((string)requestData["region_UUID"]); + simData = m_gridDBService.GetRegion(regionID); + if (simData == null) + { + m_log.WarnFormat("[DATA] didn't find region for regionID {0} from {1}", + regionID, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); + } + } + else if (requestData.ContainsKey("region_handle")) + { + //CFK: The if/else below this makes this message redundant. + //CFK: Console.WriteLine("requesting data for region " + (string) requestData["region_handle"]); + ulong regionHandle = Convert.ToUInt64((string)requestData["region_handle"]); + simData = m_gridDBService.GetRegion(regionHandle); + if (simData == null) + { + m_log.WarnFormat("[DATA] didn't find region for regionHandle {0} from {1}", + regionHandle, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); + } + } + else if (requestData.ContainsKey("region_name_search")) + { + string regionName = (string)requestData["region_name_search"]; + simData = m_gridDBService.GetRegion(regionName); + if (simData == null) + { + m_log.WarnFormat("[DATA] didn't find region for regionName {0} from {1}", + regionName, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); + } + } + else m_log.Warn("[DATA] regionlookup without regionID, regionHandle or regionHame"); + + if (simData == null) + { + //Sim does not exist + responseData["error"] = "Sim does not exist"; + } + else + { + m_log.Info("[DATA]: found " + (string)simData.regionName + " regionHandle = " + + (string)requestData["region_handle"]); + responseData["sim_ip"] = simData.serverIP; + responseData["sim_port"] = simData.serverPort.ToString(); + responseData["server_uri"] = simData.serverURI; + responseData["http_port"] = simData.httpPort.ToString(); + responseData["remoting_port"] = simData.remotingPort.ToString(); + responseData["region_locx"] = simData.regionLocX.ToString(); + responseData["region_locy"] = simData.regionLocY.ToString(); + responseData["region_UUID"] = simData.UUID.Guid.ToString(); + responseData["region_name"] = simData.regionName; + responseData["regionHandle"] = simData.regionHandle.ToString(); + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = responseData; + return response; + } + + public XmlRpcResponse XmlRpcMapBlockMethod(XmlRpcRequest request) + { + int xmin = 980, ymin = 980, xmax = 1020, ymax = 1020; + + Hashtable requestData = (Hashtable)request.Params[0]; + if (requestData.ContainsKey("xmin")) + { + xmin = (Int32)requestData["xmin"]; + } + if (requestData.ContainsKey("ymin")) + { + ymin = (Int32)requestData["ymin"]; + } + if (requestData.ContainsKey("xmax")) + { + xmax = (Int32)requestData["xmax"]; + } + if (requestData.ContainsKey("ymax")) + { + ymax = (Int32)requestData["ymax"]; + } + //CFK: The second log is more meaningful and either standard or fast generally occurs. + //CFK: m_log.Info("[MAP]: World map request for range (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); + + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + response.Value = responseData; + IList simProfileList = new ArrayList(); + + bool fastMode = (m_config.DatabaseProvider == "OpenSim.Data.MySQL.dll" || m_config.DatabaseProvider == "OpenSim.Data.MSSQL.dll"); + + if (fastMode) + { + List neighbours = m_gridDBService.GetRegions((uint)xmin, (uint)ymin, (uint)xmax, (uint)ymax); + + foreach (RegionProfileData aSim in neighbours) + { + Hashtable simProfileBlock = new Hashtable(); + simProfileBlock["x"] = aSim.regionLocX.ToString(); + simProfileBlock["y"] = aSim.regionLocY.ToString(); + //m_log.DebugFormat("[MAP]: Sending neighbour info for {0},{1}", aSim.regionLocX, aSim.regionLocY); + simProfileBlock["name"] = aSim.regionName; + simProfileBlock["access"] = 21; + simProfileBlock["region-flags"] = 512; + simProfileBlock["water-height"] = 0; + simProfileBlock["agents"] = 1; + simProfileBlock["map-image-id"] = aSim.regionMapTextureID.ToString(); + + // For Sugilite compatibility + simProfileBlock["regionhandle"] = aSim.regionHandle.ToString(); + simProfileBlock["sim_ip"] = aSim.serverIP; + simProfileBlock["sim_port"] = aSim.serverPort.ToString(); + simProfileBlock["sim_uri"] = aSim.serverURI.ToString(); + simProfileBlock["uuid"] = aSim.UUID.ToString(); + simProfileBlock["remoting_port"] = aSim.remotingPort.ToString(); + simProfileBlock["http_port"] = aSim.httpPort.ToString(); + + simProfileList.Add(simProfileBlock); + } + m_log.Info("[MAP]: Fast map " + simProfileList.Count.ToString() + + " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); + } + else + { + RegionProfileData simProfile; + for (int x = xmin; x < xmax + 1; x++) + { + for (int y = ymin; y < ymax + 1; y++) + { + ulong regHandle = Utils.UIntsToLong((uint)(x * Constants.RegionSize), (uint)(y * Constants.RegionSize)); + simProfile = m_gridDBService.GetRegion(regHandle); + if (simProfile != null) + { + Hashtable simProfileBlock = new Hashtable(); + simProfileBlock["x"] = x; + simProfileBlock["y"] = y; + simProfileBlock["name"] = simProfile.regionName; + simProfileBlock["access"] = 0; + simProfileBlock["region-flags"] = 0; + simProfileBlock["water-height"] = 20; + simProfileBlock["agents"] = 1; + simProfileBlock["map-image-id"] = simProfile.regionMapTextureID.ToString(); + + // For Sugilite compatibility + simProfileBlock["regionhandle"] = simProfile.regionHandle.ToString(); + simProfileBlock["sim_ip"] = simProfile.serverIP.ToString(); + simProfileBlock["sim_port"] = simProfile.serverPort.ToString(); + simProfileBlock["sim_uri"] = simProfile.serverURI.ToString(); + simProfileBlock["uuid"] = simProfile.UUID.ToString(); + simProfileBlock["remoting_port"] = simProfile.remotingPort.ToString(); + simProfileBlock["http_port"] = simProfile.httpPort; + + simProfileList.Add(simProfileBlock); + } + } + } + m_log.Info("[MAP]: Std map " + simProfileList.Count.ToString() + + " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); + } + + responseData["sim-profiles"] = simProfileList; + + return response; + } + + /// + /// Returns up to maxNumber profiles of regions that have a name starting with name + /// + /// + /// + public XmlRpcResponse XmlRpcSearchForRegionMethod(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable)request.Params[0]; + + if (!requestData.ContainsKey("name") || !requestData.Contains("maxNumber")) + { + m_log.Warn("[DATA] Invalid region-search request; missing name or maxNumber"); + return new XmlRpcResponse(500, "Missing name or maxNumber in region search request"); + } + + Hashtable responseData = new Hashtable(); + + string name = (string)requestData["name"]; + int maxNumber = Convert.ToInt32((string)requestData["maxNumber"]); + if (maxNumber == 0 || name.Length < 3) + { + // either we didn't want any, or we were too unspecific + responseData["numFound"] = 0; + } + else + { + List sims = m_gridDBService.GetRegions(name, maxNumber); + + responseData["numFound"] = sims.Count; + for (int i = 0; i < sims.Count; ++i) + { + RegionProfileData sim = sims[i]; + string prefix = "region" + i + "."; + responseData[prefix + "region_name"] = sim.regionName; + responseData[prefix + "region_UUID"] = sim.UUID.ToString(); + responseData[prefix + "region_locx"] = sim.regionLocX.ToString(); + responseData[prefix + "region_locy"] = sim.regionLocY.ToString(); + responseData[prefix + "sim_ip"] = sim.serverIP.ToString(); + responseData[prefix + "sim_port"] = sim.serverPort.ToString(); + responseData[prefix + "remoting_port"] = sim.remotingPort.ToString(); + responseData[prefix + "http_port"] = sim.httpPort.ToString(); + responseData[prefix + "map_UUID"] = sim.regionMapTextureID.ToString(); + } + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = responseData; + return response; + } + + /// + /// Construct an XMLRPC registration disabled response + /// + /// + /// + public static XmlRpcResponse XmlRPCRegionRegistrationDisabledResponse(string error) + { + XmlRpcResponse errorResponse = new XmlRpcResponse(); + Hashtable errorResponseData = new Hashtable(); + errorResponse.Value = errorResponseData; + errorResponseData["restricted"] = error; + return errorResponse; + } + } + + /// + /// Exception generated when a simulator fails to login to the grid + /// + public class LoginException : Exception + { + /// + /// Return an XmlRpcResponse version of the exception message suitable for sending to a client + /// + /// + /// + public XmlRpcResponse XmlRpcErrorResponse + { + get { return m_xmlRpcErrorResponse; } + } + private XmlRpcResponse m_xmlRpcErrorResponse; + + public LoginException(string message, string xmlRpcMessage) : base(message) + { + // FIXME: Might be neater to refactor and put the method inside here + m_xmlRpcErrorResponse = GridXmlRpcModule.ErrorResponse(xmlRpcMessage); + } + + public LoginException(string message, string xmlRpcMessage, Exception e) : base(message, e) + { + // FIXME: Might be neater to refactor and put the method inside here + m_xmlRpcErrorResponse = GridXmlRpcModule.ErrorResponse(xmlRpcMessage); + } + } +} diff --git a/OpenSim/Grid/GridServer/IGridCore.cs b/OpenSim/Grid/GridServer/IGridCore.cs new file mode 100644 index 0000000..dd0d140 --- /dev/null +++ b/OpenSim/Grid/GridServer/IGridCore.cs @@ -0,0 +1,13 @@ +using System; +using OpenSim.Framework.Servers; + +namespace OpenSim.Grid.GridServer +{ + public interface IGridCore + { + T Get(); + void RegisterInterface(T iface); + bool TryGet(out T iface); + BaseHttpServer GetHttpServer(); + } +} diff --git a/OpenSim/Grid/GridServer/IGridMessagingModule.cs b/OpenSim/Grid/GridServer/IGridMessagingModule.cs new file mode 100644 index 0000000..969910e --- /dev/null +++ b/OpenSim/Grid/GridServer/IGridMessagingModule.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using OpenSim.Framework.Servers; + +namespace OpenSim.Grid.GridServer +{ + public interface IGridMessagingModule + { + List MessageServers { get; } + } +} -- cgit v1.1