From 134f86e8d5c414409631b25b8c6f0ee45fbd8631 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Thu, 3 Nov 2016 21:44:39 +1000 Subject: Initial update to OpenSim 0.8.2.1 source code. --- OpenSim/Services/AssetService/AssetService.cs | 51 +- .../AssetService/Properties/AssemblyInfo.cs | 4 +- OpenSim/Services/AssetService/XAssetService.cs | 77 ++- OpenSim/Services/AssetService/XAssetServiceBase.cs | 47 +- .../Properties/AssemblyInfo.cs | 4 +- .../Properties/AssemblyInfo.cs | 4 +- .../AvatarService/Properties/AssemblyInfo.cs | 4 +- OpenSim/Services/Base/Properties/AssemblyInfo.cs | 4 +- OpenSim/Services/Base/ServiceBase.cs | 13 +- .../AgentPreferences/AgentPreferencesConnector.cs | 230 +++++++ .../Connectors/Asset/AssetServicesConnector.cs | 118 ++-- .../Connectors/Asset/HGAssetServiceConnector.cs | 104 +-- .../AuthenticationServicesConnector.cs | 14 +- .../AuthorizationServicesConnector.cs | 3 +- .../Connectors/Avatar/AvatarServicesConnector.cs | 17 +- .../Services/Connectors/BaseServiceConnector.cs | 33 + .../Connectors/Estate/EstateDataConnector.cs | 338 ++++++++++ .../Freeswitch/RemoteFreeswitchConnector.cs | 2 +- .../Connectors/Friends/FriendsServicesConnector.cs | 12 +- .../Connectors/Grid/GridServicesConnector.cs | 121 +++- .../GridUser/GridUserServicesConnector.cs | 17 +- .../Hypergrid/GatekeeperServiceConnector.cs | 99 ++- .../Hypergrid/HGFriendsServicesConnector.cs | 2 +- .../Connectors/Hypergrid/HeloServicesConnector.cs | 57 +- .../Hypergrid/UserAgentServiceConnector.cs | 591 +++++------------ .../InstantMessageServiceConnector.cs | 1 + .../Inventory/XInventoryServicesConnector.cs | 405 ++++++++---- .../Connectors/Land/LandServicesConnector.cs | 4 +- .../MapImage/MapImageServicesConnector.cs | 83 ++- .../Neighbour/NeighbourServicesConnector.cs | 72 +- .../Presence/PresenceServicesConnector.cs | 26 +- .../Services/Connectors/Properties/AssemblyInfo.cs | 4 +- .../SimianGrid/SimianActivityDetector.cs | 4 +- .../SimianGrid/SimianAssetServiceConnector.cs | 526 ++++++++++----- .../SimianAuthenticationServiceConnector.cs | 12 +- .../SimianGrid/SimianAvatarServiceConnector.cs | 8 +- .../SimianGrid/SimianExternalCapsModule.cs | 180 +++++ .../SimianGrid/SimianFriendsServiceConnector.cs | 8 +- .../Services/Connectors/SimianGrid/SimianGrid.cs | 118 +++- .../SimianGrid/SimianGridMaptileModule.cs | 118 ++-- .../SimianGrid/SimianGridServiceConnector.cs | 49 +- .../SimianGrid/SimianInventoryServiceConnector.cs | 119 ++-- .../SimianGrid/SimianPresenceServiceConnector.cs | 212 +++--- .../Connectors/SimianGrid/SimianProfiles.cs | 8 +- .../SimianUserAccountServiceConnector.cs | 13 +- .../Connectors/Simulation/EstateDataService.cs | 139 ---- .../Connectors/Simulation/SimulationDataService.cs | 182 ------ .../Simulation/SimulationServiceConnector.cs | 165 +++-- .../UserAccounts/UserAccountServicesConnector.cs | 57 +- .../Services/EstateService/EstateDataService.cs | 136 ++++ OpenSim/Services/FSAssetService/FSAssetService.cs | 723 +++++++++++++++++++++ .../FreeswitchService/Properties/AssemblyInfo.cs | 4 +- .../Services/Friends/Properties/AssemblyInfo.cs | 4 +- OpenSim/Services/GridService/GridService.cs | 415 +++++++++--- OpenSim/Services/GridService/HypergridLinker.cs | 236 +++++-- .../GridService/Properties/AssemblyInfo.cs | 4 +- .../Services/HypergridService/GatekeeperService.cs | 121 +++- .../Services/HypergridService/HGAssetService.cs | 34 +- .../Services/HypergridService/HGFSAssetService.cs | 189 ++++++ .../Services/HypergridService/HGFriendsService.cs | 3 +- .../HypergridService/HGInstantMessageService.cs | 19 +- .../HypergridService/HGInventoryService.cs | 27 +- .../HypergridService/HGSuitcaseInventoryService.cs | 258 ++++---- .../HypergridService/Properties/AssemblyInfo.cs | 4 +- .../Services/HypergridService/UserAccountCache.cs | 7 +- .../Services/HypergridService/UserAgentService.cs | 259 +++++--- .../HypergridService/UserAgentServiceBase.cs | 84 +++ .../Interfaces/IAgentPreferencesService.cs | 115 ++++ OpenSim/Services/Interfaces/IAssetService.cs | 9 +- OpenSim/Services/Interfaces/IAvatarService.cs | 46 +- .../Services/Interfaces/IBakedTextureService.cs | 38 ++ OpenSim/Services/Interfaces/IBansService.cs | 48 ++ OpenSim/Services/Interfaces/IEstateDataService.cs | 115 ++++ OpenSim/Services/Interfaces/IGridService.cs | 286 +++++--- OpenSim/Services/Interfaces/IHypergridServices.cs | 66 +- OpenSim/Services/Interfaces/IInventoryService.cs | 36 +- OpenSim/Services/Interfaces/IMapImageService.cs | 1 + OpenSim/Services/Interfaces/IOfflineIMService.cs | 7 + OpenSim/Services/Interfaces/ISimulationService.cs | 39 +- OpenSim/Services/Interfaces/IUserAccountService.cs | 2 + OpenSim/Services/Interfaces/IUserManagement.cs | 97 +++ .../Services/Interfaces/IUserProfilesService.cs | 80 +++ OpenSim/Services/Interfaces/OpenProfileClient.cs | 134 ++++ .../Services/Interfaces/Properties/AssemblyInfo.cs | 4 +- .../Services/InventoryService/LibraryService.cs | 1 + .../InventoryService/Properties/AssemblyInfo.cs | 4 +- .../Services/InventoryService/XInventoryService.cs | 172 ++--- OpenSim/Services/LLLoginService/LLLoginResponse.cs | 83 ++- OpenSim/Services/LLLoginService/LLLoginService.cs | 166 +++-- .../LLLoginService/Properties/AssemblyInfo.cs | 4 +- .../Services/MapImageService/MapImageService.cs | 110 +++- .../MapImageService/Properties/AssemblyInfo.cs | 4 +- .../Services/PresenceService/PresenceService.cs | 87 ++- .../PresenceService/Properties/AssemblyInfo.cs | 4 +- .../SimulationService/SimulationDataService.cs | 191 ++++++ .../UserAccountService/AgentPreferencesService.cs | 82 +++ .../AgentPreferencesServiceBase.cs | 73 +++ .../Services/UserAccountService/GridUserService.cs | 127 +++- .../UserAccountService/GridUserServiceBase.cs | 10 +- .../UserAccountService/Properties/AssemblyInfo.cs | 4 +- .../UserAccountService/UserAccountService.cs | 56 +- .../UserProfilesService/UserProfilesService.cs | 263 ++++++++ .../UserProfilesService/UserProfilesServiceBase.cs | 87 +++ 103 files changed, 7171 insertions(+), 2486 deletions(-) create mode 100644 OpenSim/Services/Connectors/AgentPreferences/AgentPreferencesConnector.cs create mode 100644 OpenSim/Services/Connectors/BaseServiceConnector.cs create mode 100644 OpenSim/Services/Connectors/Estate/EstateDataConnector.cs create mode 100644 OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs delete mode 100644 OpenSim/Services/Connectors/Simulation/EstateDataService.cs delete mode 100644 OpenSim/Services/Connectors/Simulation/SimulationDataService.cs create mode 100644 OpenSim/Services/EstateService/EstateDataService.cs create mode 100644 OpenSim/Services/FSAssetService/FSAssetService.cs create mode 100644 OpenSim/Services/HypergridService/HGFSAssetService.cs create mode 100644 OpenSim/Services/HypergridService/UserAgentServiceBase.cs create mode 100644 OpenSim/Services/Interfaces/IAgentPreferencesService.cs create mode 100644 OpenSim/Services/Interfaces/IBakedTextureService.cs create mode 100644 OpenSim/Services/Interfaces/IBansService.cs create mode 100644 OpenSim/Services/Interfaces/IEstateDataService.cs create mode 100644 OpenSim/Services/Interfaces/IUserManagement.cs create mode 100644 OpenSim/Services/Interfaces/IUserProfilesService.cs create mode 100644 OpenSim/Services/Interfaces/OpenProfileClient.cs create mode 100644 OpenSim/Services/SimulationService/SimulationDataService.cs create mode 100644 OpenSim/Services/UserAccountService/AgentPreferencesService.cs create mode 100644 OpenSim/Services/UserAccountService/AgentPreferencesServiceBase.cs create mode 100644 OpenSim/Services/UserProfilesService/UserProfilesService.cs create mode 100644 OpenSim/Services/UserProfilesService/UserProfilesServiceBase.cs (limited to 'OpenSim/Services') diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index e7eb6fe..0aefa16 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs @@ -123,53 +123,54 @@ namespace OpenSim.Services.AssetService public virtual AssetMetadata GetMetadata(string id) { // m_log.DebugFormat("[ASSET SERVICE]: Get asset metadata for {0}", id); - - UUID assetID; - if (!UUID.TryParse(id, out assetID)) - return null; + AssetBase asset = Get(id); - AssetBase asset = m_Database.GetAsset(assetID); if (asset != null) return asset.Metadata; - - return null; + else + return null; } public virtual byte[] GetData(string id) { // m_log.DebugFormat("[ASSET SERVICE]: Get asset data for {0}", id); - - UUID assetID; - if (!UUID.TryParse(id, out assetID)) - return null; + AssetBase asset = Get(id); - AssetBase asset = m_Database.GetAsset(assetID); - return asset.Data; + if (asset != null) + return asset.Data; + else + return null; } public virtual bool Get(string id, Object sender, AssetRetrieved handler) { //m_log.DebugFormat("[AssetService]: Get asset async {0}", id); - - UUID assetID; - if (!UUID.TryParse(id, out assetID)) - return false; - - AssetBase asset = m_Database.GetAsset(assetID); - - //m_log.DebugFormat("[AssetService]: Got asset {0}", asset); - - handler(id, sender, asset); + handler(id, sender, Get(id)); return true; } + public virtual bool[] AssetsExist(string[] ids) + { + try + { + UUID[] uuid = Array.ConvertAll(ids, id => UUID.Parse(id)); + return m_Database.AssetsExist(uuid); + } + catch (Exception e) + { + m_log.Error("[ASSET SERVICE]: Exception getting assets ", e); + return new bool[ids.Length]; + } + } + public virtual string Store(AssetBase asset) { - if (!m_Database.ExistsAsset(asset.FullID)) + bool exists = m_Database.AssetsExist(new[] { asset.FullID })[0]; + if (!exists) { // m_log.DebugFormat( // "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length); @@ -200,4 +201,4 @@ namespace OpenSim.Services.AssetService return m_Database.Delete(id); } } -} \ No newline at end of file +} diff --git a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs index 1509400..63654a6 100644 --- a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/AssetService/XAssetService.cs b/OpenSim/Services/AssetService/XAssetService.cs index a1d10ed..b1e5184 100644 --- a/OpenSim/Services/AssetService/XAssetService.cs +++ b/OpenSim/Services/AssetService/XAssetService.cs @@ -39,16 +39,18 @@ using OpenMetaverse; namespace OpenSim.Services.AssetService { /// - /// This will be developed into a de-duplicating asset service. - /// XXX: Currently it's a just a copy of the existing AssetService. so please don't attempt to use it. + /// A de-duplicating asset service. /// + [Obsolete] public class XAssetService : XAssetServiceBase, IAssetService { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected static XAssetService m_RootInstance; - public XAssetService(IConfigSource config) : base(config) + public XAssetService(IConfigSource config) : this(config, "AssetService") {} + + public XAssetService(IConfigSource config, string configName) : base(config, configName) { if (m_RootInstance == null) { @@ -56,22 +58,21 @@ namespace OpenSim.Services.AssetService if (m_AssetLoader != null) { - IConfig assetConfig = config.Configs["AssetService"]; + IConfig assetConfig = config.Configs[configName]; if (assetConfig == null) throw new Exception("No AssetService configuration"); - string loaderArgs = assetConfig.GetString("AssetLoaderArgs", - String.Empty); + string loaderArgs = assetConfig.GetString("AssetLoaderArgs", String.Empty); bool assetLoaderEnabled = assetConfig.GetBoolean("AssetLoaderEnabled", true); - if (assetLoaderEnabled) + if (assetLoaderEnabled && !HasChainedAssetService) { m_log.DebugFormat("[XASSET SERVICE]: Loading default asset set from {0}", loaderArgs); m_AssetLoader.ForEachDefaultXmlAsset( loaderArgs, - delegate(AssetBase a) + a => { AssetBase existingAsset = Get(a.ID); // AssetMetadata existingMetadata = GetMetadata(a.ID); @@ -85,6 +86,7 @@ namespace OpenSim.Services.AssetService } m_log.Debug("[XASSET SERVICE]: Local asset service enabled"); + m_log.Error("[XASSET SERVICE]: THIS ASSET SERVICE HAS BEEN MARKED OBSOLETE. PLEASE USE FSAssetService"); } } } @@ -103,7 +105,23 @@ namespace OpenSim.Services.AssetService try { - return m_Database.GetAsset(assetID); + AssetBase asset = m_Database.GetAsset(assetID); + + if (asset != null) + { + return asset; + } + else if (HasChainedAssetService) + { + asset = m_ChainedAssetService.Get(id); + + if (asset != null) + MigrateFromChainedService(asset); + + return asset; + } + + return null; } catch (Exception e) { @@ -120,30 +138,25 @@ namespace OpenSim.Services.AssetService public virtual AssetMetadata GetMetadata(string id) { // m_log.DebugFormat("[XASSET SERVICE]: Get asset metadata for {0}", id); - - UUID assetID; - if (!UUID.TryParse(id, out assetID)) - return null; + AssetBase asset = Get(id); - AssetBase asset = m_Database.GetAsset(assetID); if (asset != null) return asset.Metadata; - - return null; + else + return null; } public virtual byte[] GetData(string id) { // m_log.DebugFormat("[XASSET SERVICE]: Get asset data for {0}", id); - UUID assetID; + AssetBase asset = Get(id); - if (!UUID.TryParse(id, out assetID)) + if (asset != null) + return asset.Data; + else return null; - - AssetBase asset = m_Database.GetAsset(assetID); - return asset.Data; } public virtual bool Get(string id, Object sender, AssetRetrieved handler) @@ -155,7 +168,7 @@ namespace OpenSim.Services.AssetService if (!UUID.TryParse(id, out assetID)) return false; - AssetBase asset = m_Database.GetAsset(assetID); + AssetBase asset = Get(id); //m_log.DebugFormat("[XASSET SERVICE]: Got asset {0}", asset); @@ -164,9 +177,16 @@ namespace OpenSim.Services.AssetService return true; } + public virtual bool[] AssetsExist(string[] ids) + { + UUID[] uuid = Array.ConvertAll(ids, id => UUID.Parse(id)); + return m_Database.AssetsExist(uuid); + } + public virtual string Store(AssetBase asset) { - if (!m_Database.ExistsAsset(asset.FullID)) + bool exists = m_Database.AssetsExist(new[] { asset.FullID })[0]; + if (!exists) { // m_log.DebugFormat( // "[XASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length); @@ -194,7 +214,16 @@ namespace OpenSim.Services.AssetService if (!UUID.TryParse(id, out assetID)) return false; + if (HasChainedAssetService) + m_ChainedAssetService.Delete(id); + return m_Database.Delete(id); } + + private void MigrateFromChainedService(AssetBase asset) + { + Store(asset); + m_ChainedAssetService.Delete(asset.ID); + } } -} \ No newline at end of file +} diff --git a/OpenSim/Services/AssetService/XAssetServiceBase.cs b/OpenSim/Services/AssetService/XAssetServiceBase.cs index 0c5c2c3..c118c9d 100644 --- a/OpenSim/Services/AssetService/XAssetServiceBase.cs +++ b/OpenSim/Services/AssetService/XAssetServiceBase.cs @@ -27,9 +27,11 @@ using System; using System.Reflection; +using log4net; using Nini.Config; using OpenSim.Framework; using OpenSim.Data; +using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenSim.Services.Base; @@ -37,10 +39,15 @@ namespace OpenSim.Services.AssetService { public class XAssetServiceBase : ServiceBase { - protected IXAssetDataPlugin m_Database = null; - protected IAssetLoader m_AssetLoader = null; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public XAssetServiceBase(IConfigSource config) : base(config) + protected IXAssetDataPlugin m_Database; + protected IAssetLoader m_AssetLoader; + protected IAssetService m_ChainedAssetService; + + protected bool HasChainedAssetService { get { return m_ChainedAssetService != null; } } + + public XAssetServiceBase(IConfigSource config, string configName) : base(config) { string dllName = String.Empty; string connString = String.Empty; @@ -48,7 +55,7 @@ namespace OpenSim.Services.AssetService // // Try reading the [AssetService] section first, if it exists // - IConfig assetConfig = config.Configs["AssetService"]; + IConfig assetConfig = config.Configs[configName]; if (assetConfig != null) { dllName = assetConfig.GetString("StorageProvider", dllName); @@ -77,17 +84,35 @@ namespace OpenSim.Services.AssetService if (m_Database == null) throw new Exception("Could not find a storage interface in the given module"); - m_Database.Initialise(connString); + string chainedAssetServiceDesignator = assetConfig.GetString("ChainedServiceModule", null); + + if (chainedAssetServiceDesignator != null) + { + m_log.InfoFormat( + "[XASSET SERVICE BASE]: Loading chained asset service from {0}", chainedAssetServiceDesignator); - string loaderName = assetConfig.GetString("DefaultAssetLoader", - String.Empty); + Object[] args = new Object[] { config, configName }; + m_ChainedAssetService = ServerUtils.LoadPlugin(chainedAssetServiceDesignator, args); - if (loaderName != String.Empty) + if (!HasChainedAssetService) + throw new Exception( + String.Format("Failed to load ChainedAssetService from {0}", chainedAssetServiceDesignator)); + } + + m_Database.Initialise(connString); + + if (HasChainedAssetService) { - m_AssetLoader = LoadPlugin(loaderName); + string loaderName = assetConfig.GetString("DefaultAssetLoader", + String.Empty); + + if (loaderName != String.Empty) + { + m_AssetLoader = LoadPlugin(loaderName); - if (m_AssetLoader == null) - throw new Exception("Asset loader could not be loaded"); + if (m_AssetLoader == null) + throw new Exception("Asset loader could not be loaded"); + } } } } diff --git a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs index 0eb2ba7..f25accc 100644 --- a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs index 6d6b11e..47d47ab 100644 --- a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs index 0944149..a233d8a 100644 --- a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/Base/Properties/AssemblyInfo.cs b/OpenSim/Services/Base/Properties/AssemblyInfo.cs index 306b699..b113c42 100644 --- a/OpenSim/Services/Base/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/Base/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/Base/ServiceBase.cs b/OpenSim/Services/Base/ServiceBase.cs index ef30cba..a7eb2be 100644 --- a/OpenSim/Services/Base/ServiceBase.cs +++ b/OpenSim/Services/Base/ServiceBase.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Reflection; using log4net; using Nini.Config; @@ -45,9 +46,15 @@ namespace OpenSim.Services.Base public T LoadPlugin(string dllName, Object[] args) where T:class { - string[] parts = dllName.Split(new char[] {':'}); + // The path:type separator : is unfortunate because it collides + // with Windows paths like C:\... + // When the path provided includes the drive, this fails. + // Hence the root/noroot thing going on here. + string pathRoot = Path.GetPathRoot(dllName); + string noRoot = dllName.Substring(pathRoot.Length); + string[] parts = noRoot.Split(new char[] {':'}); - dllName = parts[0]; + dllName = pathRoot + parts[0]; string className = String.Empty; @@ -79,7 +86,7 @@ namespace OpenSim.Services.Base continue; Type typeInterface = - pluginType.GetInterface(interfaceName, true); + pluginType.GetInterface(interfaceName); if (typeInterface != null) { T plug = (T)Activator.CreateInstance(pluginType, diff --git a/OpenSim/Services/Connectors/AgentPreferences/AgentPreferencesConnector.cs b/OpenSim/Services/Connectors/AgentPreferences/AgentPreferencesConnector.cs new file mode 100644 index 0000000..1dbc0c8 --- /dev/null +++ b/OpenSim/Services/Connectors/AgentPreferences/AgentPreferencesConnector.cs @@ -0,0 +1,230 @@ +/* + * 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 OpenSimulator 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 log4net; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.ServiceAuth; +using OpenSim.Services.Interfaces; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using IAvatarService = OpenSim.Services.Interfaces.IAvatarService; +using OpenSim.Server.Base; +using OpenMetaverse; + +namespace OpenSim.Services.Connectors +{ + public class AgentPreferencesServicesConnector : BaseServiceConnector, IAgentPreferencesService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI = String.Empty; + + public AgentPreferencesServicesConnector() + { + } + + public AgentPreferencesServicesConnector(string serverURI) + { + m_ServerURI = serverURI.TrimEnd('/'); + } + + public AgentPreferencesServicesConnector(IConfigSource source) + : base(source, "AgentPreferencesService") + { + Initialise(source); + } + + public virtual void Initialise(IConfigSource source) + { + IConfig gridConfig = source.Configs["AgentPreferencesService"]; + if (gridConfig == null) + { + m_log.Error("[AGENT PREFERENCES CONNECTOR]: AgentPreferencesService missing from OpenSim.ini"); + throw new Exception("Agent Preferences connector init error"); + } + + string serviceURI = gridConfig.GetString("AgentPreferencesServerURI", String.Empty); + + if (serviceURI == String.Empty) + { + m_log.Error("[AGENT PREFERENCES CONNECTOR]: No Server URI named in section AgentPreferences"); + throw new Exception("Agent Preferences connector init error"); + } + m_ServerURI = serviceURI; + + base.Initialise(source, "AgentPreferencesService"); + } + + #region IAgentPreferencesService + + public AgentPrefs GetAgentPreferences(UUID principalID) + { + Dictionary sendData = new Dictionary(); + + string reply = string.Empty; + string uri = String.Concat(m_ServerURI, "/agentprefs"); + + sendData["METHOD"] = "getagentprefs"; + sendData["UserID"] = principalID; + string reqString = ServerUtils.BuildQueryString(sendData); + // m_log.DebugFormat("[AGENT PREFS CONNECTOR]: queryString = {0}", reqString); + + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); + if (String.IsNullOrEmpty(reply)) + { + m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetAgentPreferences received null or empty reply"); + return null; + } + } + catch (Exception e) + { + m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: Exception when contacting agent preferences server at {0}: {1}", uri, e.Message); + } + + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + if (replyData != null) + { + if (replyData.ContainsKey("result") && + (replyData["result"].ToString() == "null" || replyData["result"].ToString() == "Failure")) + { + m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetAgentPreferences received Failure response"); + return null; + } + } + else + { + m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetAgentPreferences received null response"); + return null; + } + AgentPrefs prefs = new AgentPrefs(replyData); + return prefs; + } + + public bool StoreAgentPreferences(AgentPrefs data) + { + Dictionary sendData = new Dictionary(); + + sendData["METHOD"] = "setagentprefs"; + + sendData["PrincipalID"] = data.PrincipalID.ToString(); + sendData["AccessPrefs"] = data.AccessPrefs; + sendData["HoverHeight"] = data.HoverHeight.ToString(); + sendData["Language"] = data.Language; + sendData["LanguageIsPublic"] = data.LanguageIsPublic.ToString(); + sendData["PermEveryone"] = data.PermEveryone.ToString(); + sendData["PermGroup"] = data.PermGroup.ToString(); + sendData["PermNextOwner"] = data.PermNextOwner.ToString(); + + string uri = String.Concat(m_ServerURI, "/agentprefs"); + string reqString = ServerUtils.BuildQueryString(sendData); + // m_log.DebugFormat("[AGENT PREFS CONNECTOR]: queryString = {0}", reqString); + + try + { + string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData.ContainsKey("result")) + { + if (replyData["result"].ToString().ToLower() == "success") + return true; + else + return false; + } + else + { + m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: StoreAgentPreferences reply data does not contain result field"); + } + + } + else + m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: StoreAgentPreferences received empty reply"); + } + catch (Exception e) + { + m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: Exception when contacting agent preferences server at {0}: {1}", uri, e.Message); + } + + return false; + } + + public string GetLang(UUID principalID) + { + Dictionary sendData = new Dictionary(); + string reply = string.Empty; + + sendData["METHOD"] = "getagentlang"; + sendData["UserID"] = principalID.ToString(); + + string uri = String.Concat(m_ServerURI, "/agentprefs"); + string reqString = ServerUtils.BuildQueryString(sendData); + + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); + if (String.IsNullOrEmpty(reply)) + { + m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetLang received null or empty reply"); + return "en-us"; // I guess? Gotta return somethin'! + } + } + catch (Exception e) + { + m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: Exception when contacting agent preferences server at {0}: {1}", uri, e.Message); + } + + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + if (replyData != null) + { + if (replyData.ContainsKey("result") && + (replyData["result"].ToString() == "null" || replyData["result"].ToString() == "Failure")) + { + m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetLang received Failure response"); + return "en-us"; + } + if (replyData.ContainsKey("Language")) + return replyData["Language"].ToString(); + } + else + { + m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetLang received null response"); + + } + return "en-us"; + } + + #endregion IAgentPreferencesService + } +} diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs index 2b2f11f..bd43552 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs @@ -33,13 +33,12 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Framework.Communications; using OpenSim.Services.Interfaces; using OpenMetaverse; namespace OpenSim.Services.Connectors { - public class AssetServicesConnector : IAssetService + public class AssetServicesConnector : BaseServiceConnector, IAssetService { private static readonly ILog m_log = LogManager.GetLogger( @@ -55,6 +54,11 @@ namespace OpenSim.Services.Connectors // Maps: Asset ID -> Handlers which will be called when the asset has been loaded private Dictionary m_AssetHandlers = new Dictionary(); + public int MaxAssetRequestConcurrency + { + get { return m_maxAssetRequestConcurrency; } + set { m_maxAssetRequestConcurrency = value; } + } public AssetServicesConnector() { @@ -66,6 +70,7 @@ namespace OpenSim.Services.Connectors } public AssetServicesConnector(IConfigSource source) + : base(source, "AssetService") { Initialise(source); } @@ -112,8 +117,16 @@ namespace OpenSim.Services.Connectors if (asset == null) { - asset = SynchronousRestObjectRequester. - MakeRequest("GET", uri, 0, m_maxAssetRequestConcurrency); + // XXX: Commented out for now since this has either never been properly operational or not for some time + // as m_maxAssetRequestConcurrency was being passed as the timeout, not a concurrency limiting option. + // Wasn't noticed before because timeout wasn't actually used. + // Not attempting concurrency setting for now as this omission was discovered in release candidate + // phase for OpenSimulator 0.8. Need to revisit afterwards. +// asset +// = SynchronousRestObjectRequester.MakeRequest( +// "GET", uri, 0, m_maxAssetRequestConcurrency); + + asset = SynchronousRestObjectRequester.MakeRequest("GET", uri, 0, m_Auth); if (m_Cache != null) m_Cache.Cache(asset); @@ -143,8 +156,7 @@ namespace OpenSim.Services.Connectors string uri = m_ServerURI + "/assets/" + id + "/metadata"; - AssetMetadata asset = SynchronousRestObjectRequester. - MakeRequest("GET", uri, 0); + AssetMetadata asset = SynchronousRestObjectRequester.MakeRequest("GET", uri, 0, m_Auth); return asset; } @@ -158,27 +170,29 @@ namespace OpenSim.Services.Connectors return fullAsset.Data; } - RestClient rc = new RestClient(m_ServerURI); - rc.AddResourcePath("assets"); - rc.AddResourcePath(id); - rc.AddResourcePath("data"); + using (RestClient rc = new RestClient(m_ServerURI)) + { + rc.AddResourcePath("assets"); + rc.AddResourcePath(id); + rc.AddResourcePath("data"); - rc.RequestMethod = "GET"; + rc.RequestMethod = "GET"; - Stream s = rc.Request(); + Stream s = rc.Request(m_Auth); - if (s == null) - return null; + if (s == null) + return null; - if (s.Length > 0) - { - byte[] ret = new byte[s.Length]; - s.Read(ret, 0, (int)s.Length); + if (s.Length > 0) + { + byte[] ret = new byte[s.Length]; + s.Read(ret, 0, (int)s.Length); - return ret; - } + return ret; + } - return null; + return null; + } } public bool Get(string id, Object sender, AssetRetrieved handler) @@ -216,7 +230,7 @@ namespace OpenSim.Services.Connectors AsynchronousRestObjectRequester.MakeRequest("GET", uri, 0, delegate(AssetBase a) { - if (m_Cache != null) + if (a != null && m_Cache != null) m_Cache.Cache(a); AssetRetrievedEx handlers; @@ -226,7 +240,7 @@ namespace OpenSim.Services.Connectors m_AssetHandlers.Remove(id); } handlers.Invoke(a); - }, m_maxAssetRequestConcurrency); + }, m_maxAssetRequestConcurrency, m_Auth); success = true; } @@ -249,9 +263,30 @@ namespace OpenSim.Services.Connectors return true; } + public virtual bool[] AssetsExist(string[] ids) + { + string uri = m_ServerURI + "/get_assets_exist"; + + bool[] exist = null; + try + { + exist = SynchronousRestObjectRequester.MakeRequest("POST", uri, ids, m_Auth); + } + catch (Exception) + { + // This is most likely to happen because the server doesn't support this function, + // so just silently return "doesn't exist" for all the assets. + } + + if (exist == null) + exist = new bool[ids.Length]; + + return exist; + } + public string Store(AssetBase asset) { - if (asset.Temporary || asset.Local) + if (asset.Local) { if (m_Cache != null) m_Cache.Cache(asset); @@ -261,27 +296,32 @@ namespace OpenSim.Services.Connectors string uri = m_ServerURI + "/assets/"; - string newID = string.Empty; + string newID; try { - newID = SynchronousRestObjectRequester. - MakeRequest("POST", uri, asset); + newID = SynchronousRestObjectRequester.MakeRequest("POST", uri, asset, m_Auth); } catch (Exception e) { - m_log.WarnFormat("[ASSET CONNECTOR]: Unable to send asset {0} to asset server. Reason: {1}", asset.ID, e.Message); + m_log.Warn(string.Format("[ASSET CONNECTOR]: Unable to send asset {0} to asset server. Reason: {1} ", asset.ID, e.Message), e); + return string.Empty; } - if (newID != String.Empty) + // TEMPORARY: SRAS returns 'null' when it's asked to store existing assets + if (newID == null) { - // Placing this here, so that this work with old asset servers that don't send any reply back - // SynchronousRestObjectRequester returns somethins that is not an empty string - if (newID != null) - asset.ID = newID; - - if (m_Cache != null) - m_Cache.Cache(asset); + m_log.DebugFormat("[ASSET CONNECTOR]: Storing of asset {0} returned null; assuming the asset already exists", asset.ID); + return asset.ID; } + + if (string.IsNullOrEmpty(newID)) + return string.Empty; + + asset.ID = newID; + + if (m_Cache != null) + m_Cache.Cache(asset); + return newID; } @@ -305,8 +345,7 @@ namespace OpenSim.Services.Connectors string uri = m_ServerURI + "/assets/" + id; - if (SynchronousRestObjectRequester. - MakeRequest("POST", uri, asset)) + if (SynchronousRestObjectRequester.MakeRequest("POST", uri, asset, m_Auth)) { if (m_Cache != null) m_Cache.Cache(asset); @@ -320,8 +359,7 @@ namespace OpenSim.Services.Connectors { string uri = m_ServerURI + "/assets/" + id; - if (SynchronousRestObjectRequester. - MakeRequest("DELETE", uri, 0)) + if (SynchronousRestObjectRequester.MakeRequest("DELETE", uri, 0, m_Auth)) { if (m_Cache != null) m_Cache.Expire(id); diff --git a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs index c395178..3710c86 100644 --- a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs @@ -36,6 +36,7 @@ using OpenSim.Framework; using OpenSim.Services.Interfaces; using OpenSim.Services.Connectors.Hypergrid; using OpenSim.Services.Connectors.SimianGrid; +using OpenMetaverse; namespace OpenSim.Services.Connectors { @@ -83,39 +84,6 @@ namespace OpenSim.Services.Connectors } } - private bool StringToUrlAndAssetID(string id, out string url, out string assetID) - { - url = String.Empty; - assetID = String.Empty; - - Uri assetUri; - - if (Uri.TryCreate(id, UriKind.Absolute, out assetUri) && - assetUri.Scheme == Uri.UriSchemeHttp) - { - // Simian - if (assetUri.Query != string.Empty) - { - NameValueCollection qscoll = HttpUtility.ParseQueryString(assetUri.Query); - assetID = qscoll["id"]; - if (assetID != null) - url = id.Replace(assetID, ""); // Malformed again, as simian expects - else - url = id; // !!! best effort - } - else // robust - { - url = "http://" + assetUri.Authority; - assetID = assetUri.LocalPath.Trim(new char[] { '/' }); - } - - return true; - } - - m_log.DebugFormat("[HG ASSET SERVICE]: Malformed URL {0}", id); - return false; - } - private IAssetService GetConnector(string url) { IAssetService connector = null; @@ -149,7 +117,7 @@ namespace OpenSim.Services.Connectors string url = string.Empty; string assetID = string.Empty; - if (StringToUrlAndAssetID(id, out url, out assetID)) + if (Util.ParseForeignAssetID(id, out url, out assetID)) { IAssetService connector = GetConnector(url); return connector.Get(assetID); @@ -163,7 +131,7 @@ namespace OpenSim.Services.Connectors string url = string.Empty; string assetID = string.Empty; - if (StringToUrlAndAssetID(id, out url, out assetID)) + if (Util.ParseForeignAssetID(id, out url, out assetID)) { IAssetService connector = GetConnector(url); return connector.GetCached(assetID); @@ -177,7 +145,7 @@ namespace OpenSim.Services.Connectors string url = string.Empty; string assetID = string.Empty; - if (StringToUrlAndAssetID(id, out url, out assetID)) + if (Util.ParseForeignAssetID(id, out url, out assetID)) { IAssetService connector = GetConnector(url); return connector.GetMetadata(assetID); @@ -196,7 +164,7 @@ namespace OpenSim.Services.Connectors string url = string.Empty; string assetID = string.Empty; - if (StringToUrlAndAssetID(id, out url, out assetID)) + if (Util.ParseForeignAssetID(id, out url, out assetID)) { IAssetService connector = GetConnector(url); return connector.Get(assetID, sender, handler); @@ -205,12 +173,72 @@ namespace OpenSim.Services.Connectors return false; } + + private struct AssetAndIndex + { + public UUID assetID; + public int index; + + public AssetAndIndex(UUID assetID, int index) + { + this.assetID = assetID; + this.index = index; + } + } + + public virtual bool[] AssetsExist(string[] ids) + { + // This method is a bit complicated because it works even if the assets belong to different + // servers; that requires sending separate requests to each server. + + // Group the assets by the server they belong to + + var url2assets = new Dictionary>(); + + for (int i = 0; i < ids.Length; i++) + { + string url = string.Empty; + string assetID = string.Empty; + + if (Util.ParseForeignAssetID(ids[i], out url, out assetID)) + { + if (!url2assets.ContainsKey(url)) + url2assets.Add(url, new List()); + url2assets[url].Add(new AssetAndIndex(UUID.Parse(assetID), i)); + } + } + + // Query each of the servers in turn + + bool[] exist = new bool[ids.Length]; + + foreach (string url in url2assets.Keys) + { + IAssetService connector = GetConnector(url); + lock (EndPointLock(connector)) + { + List curAssets = url2assets[url]; + string[] assetIDs = curAssets.ConvertAll(a => a.assetID.ToString()).ToArray(); + bool[] curExist = connector.AssetsExist(assetIDs); + + int i = 0; + foreach (AssetAndIndex ai in curAssets) + { + exist[ai.index] = curExist[i]; + ++i; + } + } + } + + return exist; + } + public string Store(AssetBase asset) { string url = string.Empty; string assetID = string.Empty; - if (StringToUrlAndAssetID(asset.ID, out url, out assetID)) + if (Util.ParseForeignAssetID(asset.ID, out url, out assetID)) { IAssetService connector = GetConnector(url); // Restore the assetID to a simple UUID diff --git a/OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs b/OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs index 2b77154..c8a4912 100644 --- a/OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs +++ b/OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs @@ -32,14 +32,14 @@ using System.IO; using System.Reflection; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Communications; +using OpenSim.Framework.ServiceAuth; using OpenSim.Services.Interfaces; using OpenSim.Server.Base; using OpenMetaverse; namespace OpenSim.Services.Connectors { - public class AuthenticationServicesConnector : IAuthenticationService + public class AuthenticationServicesConnector : BaseServiceConnector, IAuthenticationService { private static readonly ILog m_log = LogManager.GetLogger( @@ -57,6 +57,7 @@ namespace OpenSim.Services.Connectors } public AuthenticationServicesConnector(IConfigSource source) + : base(source, "AuthenticationService") { Initialise(source); } @@ -79,6 +80,8 @@ namespace OpenSim.Services.Connectors throw new Exception("Authentication connector init error"); } m_ServerURI = serviceURI; + + base.Initialise(source, "AuthenticationService"); } public string Authenticate(UUID principalID, string password, int lifetime) @@ -92,7 +95,7 @@ namespace OpenSim.Services.Connectors string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI + "/auth/plain", - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), m_Auth); Dictionary replyData = ServerUtils.ParseXmlResponse( reply); @@ -105,6 +108,7 @@ namespace OpenSim.Services.Connectors public bool Verify(UUID principalID, string token, int lifetime) { +// m_log.Error("[XXX]: Verify"); Dictionary sendData = new Dictionary(); sendData["LIFETIME"] = lifetime.ToString(); sendData["PRINCIPAL"] = principalID.ToString(); @@ -114,7 +118,7 @@ namespace OpenSim.Services.Connectors string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI + "/auth/plain", - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), m_Auth); Dictionary replyData = ServerUtils.ParseXmlResponse( reply); @@ -135,7 +139,7 @@ namespace OpenSim.Services.Connectors string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI + "/auth/plain", - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), m_Auth); Dictionary replyData = ServerUtils.ParseXmlResponse( reply); diff --git a/OpenSim/Services/Connectors/Authorization/AuthorizationServicesConnector.cs b/OpenSim/Services/Connectors/Authorization/AuthorizationServicesConnector.cs index 35b7109..d2da85f 100644 --- a/OpenSim/Services/Connectors/Authorization/AuthorizationServicesConnector.cs +++ b/OpenSim/Services/Connectors/Authorization/AuthorizationServicesConnector.cs @@ -32,7 +32,6 @@ using System.IO; using System.Reflection; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Communications; using OpenSim.Services.Interfaces; using OpenMetaverse; @@ -105,7 +104,7 @@ namespace OpenSim.Services.Connectors catch (Exception e) { m_log.WarnFormat("[AUTHORIZATION CONNECTOR]: Unable to send authorize {0} for region {1} error thrown during comms with remote server. Reason: {2}", userID, regionID, e.Message); - message = ""; + message = e.Message; return m_ResponseOnFailure; } if (response == null) diff --git a/OpenSim/Services/Connectors/Avatar/AvatarServicesConnector.cs b/OpenSim/Services/Connectors/Avatar/AvatarServicesConnector.cs index ddfca57..3f44efa 100644 --- a/OpenSim/Services/Connectors/Avatar/AvatarServicesConnector.cs +++ b/OpenSim/Services/Connectors/Avatar/AvatarServicesConnector.cs @@ -32,7 +32,7 @@ using System.IO; using System.Reflection; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Communications; +using OpenSim.Framework.ServiceAuth; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using IAvatarService = OpenSim.Services.Interfaces.IAvatarService; @@ -41,7 +41,7 @@ using OpenMetaverse; namespace OpenSim.Services.Connectors { - public class AvatarServicesConnector : IAvatarService + public class AvatarServicesConnector : BaseServiceConnector, IAvatarService { private static readonly ILog m_log = LogManager.GetLogger( @@ -59,6 +59,7 @@ namespace OpenSim.Services.Connectors } public AvatarServicesConnector(IConfigSource source) + : base(source, "AvatarService") { Initialise(source); } @@ -81,6 +82,8 @@ namespace OpenSim.Services.Connectors throw new Exception("Avatar connector init error"); } m_ServerURI = serviceURI; + + base.Initialise(source, "AvatarService"); } @@ -114,7 +117,7 @@ namespace OpenSim.Services.Connectors // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString); try { - reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString); + reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); if (reply == null || (reply != null && reply == string.Empty)) { m_log.DebugFormat("[AVATAR CONNECTOR]: GetAgent received null or empty reply"); @@ -162,7 +165,7 @@ namespace OpenSim.Services.Connectors //m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString); try { - string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString); + string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -207,7 +210,7 @@ namespace OpenSim.Services.Connectors // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString); try { - string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString); + string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -250,7 +253,7 @@ namespace OpenSim.Services.Connectors // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString); try { - string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString); + string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -293,7 +296,7 @@ namespace OpenSim.Services.Connectors // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString); try { - string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString); + string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); diff --git a/OpenSim/Services/Connectors/BaseServiceConnector.cs b/OpenSim/Services/Connectors/BaseServiceConnector.cs new file mode 100644 index 0000000..98cd489 --- /dev/null +++ b/OpenSim/Services/Connectors/BaseServiceConnector.cs @@ -0,0 +1,33 @@ +using System; +using OpenSim.Framework; +using OpenSim.Framework.ServiceAuth; + +using Nini.Config; + +namespace OpenSim.Services.Connectors +{ + public class BaseServiceConnector + { + protected IServiceAuth m_Auth; + + public BaseServiceConnector() { } + + public BaseServiceConnector(IConfigSource config, string section) + { + Initialise(config, section); + } + + public void Initialise(IConfigSource config, string section) + { + string authType = Util.GetConfigVarFromSections(config, "AuthType", new string[] { "Network", section }, "None"); + + switch (authType) + { + case "BasicHttpAuthentication": + m_Auth = new BasicHttpAuthentication(config, section); + break; + } + + } + } +} diff --git a/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs b/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs new file mode 100644 index 0000000..6412bcd --- /dev/null +++ b/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs @@ -0,0 +1,338 @@ +/* + * 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 OpenSimulator 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.Generic; +using System.Net; +using System.Reflection; + +using log4net; + +using OpenMetaverse; +using Nini.Config; + +using OpenSim.Framework; +using OpenSim.Framework.ServiceAuth; +using OpenSim.Services.Connectors; +using OpenSim.Services.Interfaces; +using OpenSim.Server.Base; + +namespace OpenSim.Services.Connectors +{ + public class EstateDataRemoteConnector : BaseServiceConnector, IEstateDataService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI = String.Empty; + private ExpiringCache> m_EstateCache = new ExpiringCache>(); + private const int EXPIRATION = 5 * 60; // 5 minutes in secs + + public EstateDataRemoteConnector(IConfigSource source) + { + Initialise(source); + } + + public virtual void Initialise(IConfigSource source) + { + IConfig gridConfig = source.Configs["EstateService"]; + if (gridConfig == null) + { + m_log.Error("[ESTATE CONNECTOR]: EstateService missing from OpenSim.ini"); + throw new Exception("Estate connector init error"); + } + + string serviceURI = gridConfig.GetString("EstateServerURI", + String.Empty); + + if (serviceURI == String.Empty) + { + m_log.Error("[ESTATE CONNECTOR]: No Server URI named in section EstateService"); + throw new Exception("Estate connector init error"); + } + m_ServerURI = serviceURI; + + base.Initialise(source, "EstateService"); + } + + #region IEstateDataService + + public List LoadEstateSettingsAll() + { + string reply = string.Empty; + string uri = m_ServerURI + "/estates"; + + reply = MakeRequest("GET", uri, string.Empty); + if (String.IsNullOrEmpty(reply)) + return new List(); + + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + List estates = new List(); + if (replyData != null && replyData.Count > 0) + { + m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettingsAll returned {0} elements", replyData.Count); + Dictionary.ValueCollection estateData = replyData.Values; + foreach (object r in estateData) + { + if (r is Dictionary) + { + EstateSettings es = new EstateSettings((Dictionary)r); + estates.Add(es); + } + } + m_EstateCache.AddOrUpdate("estates", estates, EXPIRATION); + } + else + m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettingsAll from {0} received null or zero response", uri); + + return estates; + + } + + public List GetEstatesAll() + { + List eids = new List(); + // If we don't have them, load them from the server + List estates = null; + if (!m_EstateCache.TryGetValue("estates", out estates)) + LoadEstateSettingsAll(); + + foreach (EstateSettings es in estates) + eids.Add((int)es.EstateID); + + return eids; + } + + public List GetEstates(string search) + { + // If we don't have them, load them from the server + List estates = null; + if (!m_EstateCache.TryGetValue("estates", out estates)) + LoadEstateSettingsAll(); + + List eids = new List(); + foreach (EstateSettings es in estates) + if (es.EstateName == search) + eids.Add((int)es.EstateID); + + return eids; + } + + public List GetEstatesByOwner(UUID ownerID) + { + // If we don't have them, load them from the server + List estates = null; + if (!m_EstateCache.TryGetValue("estates", out estates)) + LoadEstateSettingsAll(); + + List eids = new List(); + foreach (EstateSettings es in estates) + if (es.EstateOwner == ownerID) + eids.Add((int)es.EstateID); + + return eids; + } + + public List GetRegions(int estateID) + { + string reply = string.Empty; + // /estates/regions/?eid=int + string uri = m_ServerURI + "/estates/regions/?eid=" + estateID.ToString(); + + reply = MakeRequest("GET", uri, string.Empty); + if (String.IsNullOrEmpty(reply)) + return new List(); + + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + List regions = new List(); + if (replyData != null && replyData.Count > 0) + { + m_log.DebugFormat("[ESTATE CONNECTOR]: GetRegions for estate {0} returned {1} elements", estateID, replyData.Count); + Dictionary.ValueCollection data = replyData.Values; + foreach (object r in data) + { + UUID uuid = UUID.Zero; + if (UUID.TryParse(r.ToString(), out uuid)) + regions.Add(uuid); + } + } + else + m_log.DebugFormat("[ESTATE CONNECTOR]: GetRegions from {0} received null or zero response", uri); + + return regions; + } + + public EstateSettings LoadEstateSettings(UUID regionID, bool create) + { + string reply = string.Empty; + // /estates/estate/?region=uuid&create=[t|f] + string uri = m_ServerURI + string.Format("/estates/estate/?region={0}&create={1}", regionID, create); + + reply = MakeRequest("GET", uri, string.Empty); + if (String.IsNullOrEmpty(reply)) + return null; + + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData != null && replyData.Count > 0) + { + m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettings({0}) returned {1} elements", regionID, replyData.Count); + EstateSettings es = new EstateSettings(replyData); + return es; + } + else + m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettings(regionID) from {0} received null or zero response", uri); + + return null; + } + + public EstateSettings LoadEstateSettings(int estateID) + { + string reply = string.Empty; + // /estates/estate/?eid=int + string uri = m_ServerURI + string.Format("/estates/estate/?eid={0}", estateID); + + reply = MakeRequest("GET", uri, string.Empty); + if (String.IsNullOrEmpty(reply)) + return null; + + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData != null && replyData.Count > 0) + { + m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettings({0}) returned {1} elements", estateID, replyData.Count); + EstateSettings es = new EstateSettings(replyData); + return es; + } + else + m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettings(estateID) from {0} received null or zero response", uri); + + return null; + } + + /// + /// Forbidden operation + /// + /// + public EstateSettings CreateNewEstate() + { + // No can do + return null; + } + + public void StoreEstateSettings(EstateSettings es) + { + // /estates/estate/ + string uri = m_ServerURI + ("/estates/estate"); + + Dictionary formdata = es.ToMap(); + formdata["OP"] = "STORE"; + + PostRequest(uri, formdata); + } + + public bool LinkRegion(UUID regionID, int estateID) + { + // /estates/estate/?eid=int®ion=uuid + string uri = m_ServerURI + String.Format("/estates/estate/?eid={0}®ion={1}", estateID, regionID); + + Dictionary formdata = new Dictionary(); + formdata["OP"] = "LINK"; + return PostRequest(uri, formdata); + } + + private bool PostRequest(string uri, Dictionary sendData) + { + string reqString = ServerUtils.BuildQueryString(sendData); + + string reply = MakeRequest("POST", uri, reqString); + if (String.IsNullOrEmpty(reply)) + return false; + + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + bool result = false; + if (replyData != null && replyData.Count > 0) + { + if (replyData.ContainsKey("Result")) + { + if (Boolean.TryParse(replyData["Result"].ToString(), out result)) + m_log.DebugFormat("[ESTATE CONNECTOR]: PostRequest {0} returned {1}", uri, result); + } + } + else + m_log.DebugFormat("[ESTATE CONNECTOR]: PostRequest {0} received null or zero response", uri); + + return result; + } + + /// + /// Forbidden operation + /// + /// + public bool DeleteEstate(int estateID) + { + return false; + } + + #endregion + + private string MakeRequest(string verb, string uri, string formdata) + { + string reply = string.Empty; + try + { + reply = SynchronousRestFormsRequester.MakeRequest(verb, uri, formdata, m_Auth); + } + catch (WebException e) + { + using (HttpWebResponse hwr = (HttpWebResponse)e.Response) + { + if (hwr != null) + { + if (hwr.StatusCode == HttpStatusCode.NotFound) + m_log.Error(string.Format("[ESTATE CONNECTOR]: Resource {0} not found ", uri)); + if (hwr.StatusCode == HttpStatusCode.Unauthorized) + m_log.Error(string.Format("[ESTATE CONNECTOR]: Web request {0} requires authentication ", uri)); + } + else + m_log.Error(string.Format( + "[ESTATE CONNECTOR]: WebException for {0} {1} {2} ", + verb, uri, formdata, e)); + } + } + catch (Exception e) + { + m_log.DebugFormat("[ESTATE CONNECTOR]: Exception when contacting estate server at {0}: {1}", uri, e.Message); + } + + return reply; + } + } +} diff --git a/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs index d688299..20dc1cc 100644 --- a/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs +++ b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs @@ -32,7 +32,7 @@ using System.Collections; using System.Reflection; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Communications; + using OpenSim.Services.Interfaces; using OpenSim.Server.Base; using OpenMetaverse; diff --git a/OpenSim/Services/Connectors/Friends/FriendsServicesConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServicesConnector.cs index b1dd84e..b7702a8 100644 --- a/OpenSim/Services/Connectors/Friends/FriendsServicesConnector.cs +++ b/OpenSim/Services/Connectors/Friends/FriendsServicesConnector.cs @@ -32,7 +32,8 @@ using System.IO; using System.Reflection; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Communications; +using OpenSim.Framework.ServiceAuth; + using OpenSim.Services.Interfaces; using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; using OpenSim.Server.Base; @@ -40,7 +41,7 @@ using OpenMetaverse; namespace OpenSim.Services.Connectors.Friends { - public class FriendsServicesConnector : IFriendsService + public class FriendsServicesConnector : BaseServiceConnector, IFriendsService { private static readonly ILog m_log = LogManager.GetLogger( @@ -80,6 +81,7 @@ namespace OpenSim.Services.Connectors.Friends throw new Exception("Friends connector init error"); } m_ServerURI = serviceURI; + base.Initialise(source, "FriendsService"); } @@ -112,7 +114,7 @@ namespace OpenSim.Services.Connectors.Friends try { - string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString); + string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -168,7 +170,7 @@ namespace OpenSim.Services.Connectors.Friends string uri = m_ServerURI + "/friends"; try { - reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData)); + reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData), m_Auth); } catch (Exception e) { @@ -223,7 +225,7 @@ namespace OpenSim.Services.Connectors.Friends string uri = m_ServerURI + "/friends"; try { - reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData)); + reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData), m_Auth); } catch (Exception e) { diff --git a/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs b/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs index 34ed0d7..596f867 100644 --- a/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs +++ b/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs @@ -32,7 +32,8 @@ using System.IO; using System.Reflection; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Communications; + +using OpenSim.Framework.ServiceAuth; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Server.Base; @@ -40,7 +41,7 @@ using OpenMetaverse; namespace OpenSim.Services.Connectors { - public class GridServicesConnector : IGridService + public class GridServicesConnector : BaseServiceConnector, IGridService { private static readonly ILog m_log = LogManager.GetLogger( @@ -80,6 +81,8 @@ namespace OpenSim.Services.Connectors throw new Exception("Grid connector init error"); } m_ServerURI = serviceURI; + + base.Initialise(source, "GridService"); } @@ -102,7 +105,7 @@ namespace OpenSim.Services.Connectors // m_log.DebugFormat("[GRID CONNECTOR]: queryString = {0}", reqString); try { - string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString); + string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -158,7 +161,7 @@ namespace OpenSim.Services.Connectors try { string reply - = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData)); + = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData), m_Auth); if (reply != string.Empty) { @@ -195,7 +198,7 @@ namespace OpenSim.Services.Connectors try { - reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString); + reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); } catch (Exception e) { @@ -238,7 +241,7 @@ namespace OpenSim.Services.Connectors string uri = m_ServerURI + "/grid"; try { - reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData)); + reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData), m_Auth); } catch (Exception e) { @@ -285,7 +288,7 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), m_Auth); } catch (Exception e) { @@ -330,7 +333,7 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), m_Auth); } catch (Exception e) { @@ -374,7 +377,7 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), m_Auth); } catch (Exception e) { @@ -428,7 +431,7 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), m_Auth); //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply); } @@ -479,7 +482,7 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), m_Auth); //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply); } @@ -515,6 +518,57 @@ namespace OpenSim.Services.Connectors return rinfos; } + public List GetDefaultHypergridRegions(UUID scopeID) + { + Dictionary sendData = new Dictionary(); + + sendData["SCOPEID"] = scopeID.ToString(); + + sendData["METHOD"] = "get_default_hypergrid_regions"; + + List rinfos = new List(); + string reply = string.Empty; + string uri = m_ServerURI + "/grid"; + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", + uri, + ServerUtils.BuildQueryString(sendData), m_Auth); + + //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply); + } + catch (Exception e) + { + m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message); + return rinfos; + } + + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData != null) + { + Dictionary.ValueCollection rinfosList = replyData.Values; + foreach (object r in rinfosList) + { + if (r is Dictionary) + { + GridRegion rinfo = new GridRegion((Dictionary)r); + rinfos.Add(rinfo); + } + } + } + else + m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultHypergridRegions {0} received null response", + scopeID); + } + else + m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultHypergridRegions received null reply"); + + return rinfos; + } + public List GetFallbackRegions(UUID scopeID, int x, int y) { Dictionary sendData = new Dictionary(); @@ -532,7 +586,7 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), m_Auth); //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply); } @@ -583,7 +637,7 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), m_Auth); //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply); } @@ -634,7 +688,7 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), m_Auth); } catch (Exception e) { @@ -665,6 +719,45 @@ namespace OpenSim.Services.Connectors return flags; } + public Dictionary GetExtraFeatures() + { + Dictionary sendData = new Dictionary(); + Dictionary extraFeatures = new Dictionary(); + + sendData["METHOD"] = "get_grid_extra_features"; + + string reply = string.Empty; + string uri = m_ServerURI + "/grid"; + + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", + uri, + ServerUtils.BuildQueryString(sendData), m_Auth); + } + catch (Exception e) + { + m_log.DebugFormat("[GRID CONNECTOR]: GetExtraFeatures - Exception when contacting grid server at {0}: {1}", uri, e.Message); + return extraFeatures; + } + + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if ((replyData != null) && replyData.Count > 0) + { + foreach (string key in replyData.Keys) + { + extraFeatures[key] = replyData[key].ToString(); + } + } + } + else + m_log.DebugFormat("[GRID CONNECTOR]: GetExtraServiceURLs received null reply"); + + return extraFeatures; + } #endregion } diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs index 94bda82..b5ca1ad 100644 --- a/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs +++ b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs @@ -32,7 +32,8 @@ using System.IO; using System.Reflection; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Communications; + +using OpenSim.Framework.ServiceAuth; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Server.Base; @@ -40,7 +41,7 @@ using OpenMetaverse; namespace OpenSim.Services.Connectors { - public class GridUserServicesConnector : IGridUserService + public class GridUserServicesConnector : BaseServiceConnector, IGridUserService { private static readonly ILog m_log = LogManager.GetLogger( @@ -80,6 +81,7 @@ namespace OpenSim.Services.Connectors throw new Exception("GridUser connector init error"); } m_ServerURI = serviceURI; + base.Initialise(source, "GridUserService"); } @@ -162,7 +164,8 @@ namespace OpenSim.Services.Connectors { string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -198,7 +201,8 @@ namespace OpenSim.Services.Connectors { string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -214,7 +218,7 @@ namespace OpenSim.Services.Connectors } else - m_log.DebugFormat("[GRID USER CONNECTOR]: Loggedin received empty reply"); + m_log.DebugFormat("[GRID USER CONNECTOR]: Get received empty reply"); } catch (Exception e) { @@ -243,7 +247,8 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply == null || (reply != null && reply == string.Empty)) { m_log.DebugFormat("[GRID USER CONNECTOR]: GetGridUserInfo received null or empty reply"); diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 5bcff48..b1663ee 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -53,7 +53,8 @@ namespace OpenSim.Services.Connectors.Hypergrid private IAssetService m_AssetService; - public GatekeeperServiceConnector() : base() + public GatekeeperServiceConnector() + : base() { } @@ -123,11 +124,13 @@ namespace OpenSim.Services.Connectors.Hypergrid realHandle = Convert.ToUInt64((string)hash["handle"]); //m_log.Debug(">> HERE, realHandle: " + realHandle); } - if (hash["region_image"] != null) { + if (hash["region_image"] != null) + { imageURL = (string)hash["region_image"]; //m_log.Debug(">> HERE, imageURL: " + imageURL); } - if (hash["external_name"] != null) { + if (hash["external_name"] != null) + { externalName = (string)hash["external_name"]; //m_log.Debug(">> HERE, externalName: " + externalName); } @@ -178,7 +181,7 @@ namespace OpenSim.Services.Connectors.Hypergrid //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width); imageData = OpenJPEG.EncodeFromImage(bitmap, true); } - + AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString()); // !!! for now @@ -199,10 +202,16 @@ namespace OpenSim.Services.Connectors.Hypergrid return mapTile; } - public GridRegion GetHyperlinkRegion(GridRegion gatekeeper, UUID regionID) + public GridRegion GetHyperlinkRegion(GridRegion gatekeeper, UUID regionID, UUID agentID, string agentHomeURI, out string message) { Hashtable hash = new Hashtable(); hash["region_uuid"] = regionID.ToString(); + if (agentID != UUID.Zero) + { + hash["agent_id"] = agentID.ToString(); + if (agentHomeURI != null) + hash["agent_home_uri"] = agentHomeURI; + } IList paramList = new ArrayList(); paramList.Add(hash); @@ -216,12 +225,14 @@ namespace OpenSim.Services.Connectors.Hypergrid } catch (Exception e) { + message = "Error contacting grid."; m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message); return null; } if (response.IsFault) { + message = "Error contacting grid."; m_log.ErrorFormat("[GATEKEEPER SERVICE CONNECTOR]: remote call returned an error: {0}", response.FaultString); return null; } @@ -233,6 +244,14 @@ namespace OpenSim.Services.Connectors.Hypergrid { bool success = false; Boolean.TryParse((string)hash["result"], out success); + + if (hash["message"] != null) + message = (string)hash["message"]; + else if (success) + message = null; + else + message = "The teleport destination could not be found."; // probably the dest grid is old and doesn't send 'message', but the most common problem is that the region is unavailable + if (success) { GridRegion region = new GridRegion(); @@ -252,12 +271,25 @@ namespace OpenSim.Services.Connectors.Hypergrid region.RegionLocY = n; //m_log.Debug(">> HERE, y: " + region.RegionLocY); } + if (hash["size_x"] != null) + { + Int32.TryParse((string)hash["size_x"], out n); + region.RegionSizeX = n; + //m_log.Debug(">> HERE, x: " + region.RegionLocX); + } + if (hash["size_y"] != null) + { + Int32.TryParse((string)hash["size_y"], out n); + region.RegionSizeY = n; + //m_log.Debug(">> HERE, y: " + region.RegionLocY); + } if (hash["region_name"] != null) { region.RegionName = (string)hash["region_name"]; //m_log.Debug(">> HERE, region_name: " + region.RegionName); } - if (hash["hostname"] != null) { + if (hash["hostname"] != null) + { region.ExternalHostName = (string)hash["hostname"]; //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); } @@ -275,10 +307,10 @@ namespace OpenSim.Services.Connectors.Hypergrid region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p); //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); } - + if (hash["server_uri"] != null) { - region.ServerURI = (string) hash["server_uri"]; + region.ServerURI = (string)hash["server_uri"]; //m_log.Debug(">> HERE, server_uri: " + region.ServerURI); } @@ -289,61 +321,12 @@ namespace OpenSim.Services.Connectors.Hypergrid } catch (Exception e) { + message = "Error parsing response from grid."; m_log.Error("[GATEKEEPER SERVICE CONNECTOR]: Got exception while parsing hyperlink response " + e.StackTrace); return null; } return null; } - - public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason) - { - // m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: CreateAgent start"); - - myipaddress = String.Empty; - reason = String.Empty; - - if (destination == null) - { - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Given destination is null"); - return false; - } - - string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; - - try - { - OSDMap args = aCircuit.PackAgentCircuitData(); - - args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); - args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); - args["destination_name"] = OSD.FromString(destination.RegionName); - args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); - args["teleport_flags"] = OSD.FromString(flags.ToString()); - - OSDMap result = WebUtil.PostToService(uri, args, 80000); - if (result["Success"].AsBoolean()) - { - OSDMap unpacked = (OSDMap)result["_Result"]; - - if (unpacked != null) - { - reason = unpacked["reason"].AsString(); - myipaddress = unpacked["your_ip"].AsString(); - return unpacked["success"].AsBoolean(); - } - } - - reason = result["Message"] != null ? result["Message"].AsString() : "error"; - return false; - } - catch (Exception e) - { - m_log.Warn("[REMOTE SIMULATION CONNECTOR]: CreateAgent failed with exception: " + e.ToString()); - reason = e.Message; - } - - return false; - } } } diff --git a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs index e984a54..622d4e1 100644 --- a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs @@ -277,7 +277,7 @@ namespace OpenSim.Services.Connectors.Hypergrid { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - ServerUtils.BuildQueryString(sendData)); + ServerUtils.BuildQueryString(sendData), 15); } catch (Exception e) { diff --git a/OpenSim/Services/Connectors/Hypergrid/HeloServicesConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HeloServicesConnector.cs index 5c50936..b5e6d69 100644 --- a/OpenSim/Services/Connectors/Hypergrid/HeloServicesConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/HeloServicesConnector.cs @@ -47,16 +47,22 @@ namespace OpenSim.Services.Connectors public HeloServicesConnector(string serverURI) { - if (!serverURI.EndsWith("=")) - m_ServerURI = serverURI.TrimEnd('/') + "/helo/"; - else + try { - // Simian sends malformed urls like this: - // http://valley.virtualportland.org/simtest/Grid/?id= - // - try + Uri uri; + + if (!serverURI.EndsWith("=")) + { + // Let's check if this is a valid URI, because it may not be + uri = new Uri(serverURI); + m_ServerURI = serverURI.TrimEnd('/') + "/helo/"; + } + else { - Uri uri = new Uri(serverURI + "xxx"); + // Simian sends malformed urls like this: + // http://valley.virtualportland.org/simtest/Grid/?id= + // + uri = new Uri(serverURI + "xxx"); if (uri.Query == string.Empty) m_ServerURI = serverURI.TrimEnd('/') + "/helo/"; else @@ -66,26 +72,34 @@ namespace OpenSim.Services.Connectors m_ServerURI = m_ServerURI.TrimEnd('/') + "/helo/"; } } - catch (UriFormatException) - { - m_log.WarnFormat("[HELO SERVICE]: Malformed URL {0}", serverURI); - } + + } + catch (UriFormatException) + { + m_log.WarnFormat("[HELO SERVICE]: Malformed URL {0}", serverURI); } } - public virtual string Helo() { - HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI); - // Eventually we need to switch to HEAD - /* req.Method = "HEAD"; */ + if (String.IsNullOrEmpty(m_ServerURI)) + { + m_log.WarnFormat("[HELO SERVICE]: Unable to invoke HELO due to empty URL"); + return String.Empty; + } try { - WebResponse response = req.GetResponse(); - if (response.Headers.Get("X-Handlers-Provided") == null) // just in case this ever returns a null - return string.Empty; - return response.Headers.Get("X-Handlers-Provided"); + HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI); + // Eventually we need to switch to HEAD + /* req.Method = "HEAD"; */ + + using (WebResponse response = req.GetResponse()) + { + if (response.Headers.Get("X-Handlers-Provided") == null) // just in case this ever returns a null + return string.Empty; + return response.Headers.Get("X-Handlers-Provided"); + } } catch (Exception e) { @@ -95,6 +109,5 @@ namespace OpenSim.Services.Connectors // fail return string.Empty; } - } -} +} \ No newline at end of file diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 2f263ae..8abd046 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -44,13 +44,15 @@ using Nini.Config; namespace OpenSim.Services.Connectors.Hypergrid { - public class UserAgentServiceConnector : IUserAgentService + public class UserAgentServiceConnector : SimulationServiceConnector, IUserAgentService { private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); - string m_ServerURL; + private string m_ServerURLHost; + private string m_ServerURL; + private GridRegion m_Gatekeeper; public UserAgentServiceConnector(string url) : this(url, true) { @@ -58,7 +60,7 @@ namespace OpenSim.Services.Connectors.Hypergrid public UserAgentServiceConnector(string url, bool dnsLookup) { - m_ServerURL = url; + m_ServerURL = m_ServerURLHost = url; if (dnsLookup) { @@ -74,10 +76,11 @@ namespace OpenSim.Services.Connectors.Hypergrid } catch (Exception e) { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Malformed Uri {0}: {1}", m_ServerURL, e.Message); + m_log.DebugFormat("[USER AGENT CONNECTOR]: Malformed Uri {0}: {1}", url, e.Message); } } - m_log.DebugFormat("[USER AGENT CONNECTOR]: new connector to {0} ({1})", url, m_ServerURL); + + //m_log.DebugFormat("[USER AGENT CONNECTOR]: new connector to {0} ({1})", url, m_ServerURL); } public UserAgentServiceConnector(IConfigSource config) @@ -97,16 +100,23 @@ namespace OpenSim.Services.Connectors.Hypergrid m_log.Error("[USER AGENT CONNECTOR]: No Server URI named in section UserAgentService"); throw new Exception("UserAgent connector init error"); } - m_ServerURL = serviceURI; + + m_ServerURL = m_ServerURLHost = serviceURI; if (!m_ServerURL.EndsWith("/")) m_ServerURL += "/"; - m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL); + //m_log.DebugFormat("[USER AGENT CONNECTOR]: new connector to {0}", m_ServerURL); } + protected override string AgentPath() + { + return "homeagent/"; + } - // The Login service calls this interface with a non-null [client] ipaddress - public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress, out string reason) + // The Login service calls this interface with fromLogin=true + // Sims call it with fromLogin=false + // Either way, this is verified by the handler + public bool LoginAgentToGrid(GridRegion source, AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, bool fromLogin, out string reason) { reason = String.Empty; @@ -117,151 +127,34 @@ namespace OpenSim.Services.Connectors.Hypergrid return false; } - string uri = m_ServerURL + "homeagent/" + aCircuit.AgentID + "/"; - - Console.WriteLine(" >>> LoginAgentToGrid <<< " + uri); - - HttpWebRequest AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri); - AgentCreateRequest.Method = "POST"; - AgentCreateRequest.ContentType = "application/json"; - AgentCreateRequest.Timeout = 10000; - //AgentCreateRequest.KeepAlive = false; - //AgentCreateRequest.Headers.Add("Authorization", authKey); - - // Fill it in - OSDMap args = PackCreateAgentArguments(aCircuit, gatekeeper, destination, ipaddress); - - string strBuffer = ""; - byte[] buffer = new byte[1]; - try - { - strBuffer = OSDParser.SerializeJsonString(args); - Encoding str = Util.UTF8; - buffer = str.GetBytes(strBuffer); - - } - catch (Exception e) - { - m_log.WarnFormat("[USER AGENT CONNECTOR]: Exception thrown on serialization of ChildCreate: {0}", e.Message); - // ignore. buffer will be empty, caller should check. - } - - Stream os = null; - try - { // send the Post - AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send - os = AgentCreateRequest.GetRequestStream(); - os.Write(buffer, 0, strBuffer.Length); //Send it - m_log.InfoFormat("[USER AGENT CONNECTOR]: Posted CreateAgent request to remote sim {0}, region {1}, x={2} y={3}", - uri, destination.RegionName, destination.RegionLocX, destination.RegionLocY); - } - //catch (WebException ex) - catch - { - //m_log.InfoFormat("[USER AGENT CONNECTOR]: Bad send on ChildAgentUpdate {0}", ex.Message); - reason = "cannot contact remote region"; - return false; - } - finally - { - if (os != null) - os.Close(); - } - - // Let's wait for the response - //m_log.Info("[USER AGENT CONNECTOR]: Waiting for a reply after DoCreateChildAgentCall"); + GridRegion home = new GridRegion(); + home.ServerURI = m_ServerURL; + home.RegionID = destination.RegionID; + home.RegionLocX = destination.RegionLocX; + home.RegionLocY = destination.RegionLocY; - WebResponse webResponse = null; - StreamReader sr = null; - try - { - webResponse = AgentCreateRequest.GetResponse(); - if (webResponse == null) - { - m_log.Info("[USER AGENT CONNECTOR]: Null reply on DoCreateChildAgentCall post"); - } - else - { + m_Gatekeeper = gatekeeper; - sr = new StreamReader(webResponse.GetResponseStream()); - string response = sr.ReadToEnd().Trim(); - m_log.InfoFormat("[USER AGENT CONNECTOR]: DoCreateChildAgentCall reply was {0} ", response); - - if (!String.IsNullOrEmpty(response)) - { - try - { - // we assume we got an OSDMap back - OSDMap r = Util.GetOSDMap(response); - bool success = r["success"].AsBoolean(); - reason = r["reason"].AsString(); - return success; - } - catch (NullReferenceException e) - { - m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", e.Message); - - // check for old style response - if (response.ToLower().StartsWith("true")) - return true; - - return false; - } - } - } - } - catch (WebException ex) - { - m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", ex.Message); - reason = "Destination did not reply"; - return false; - } - finally - { - if (sr != null) - sr.Close(); - } - - return true; + Console.WriteLine(" >>> LoginAgentToGrid <<< " + home.ServerURI); + uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome; + return CreateAgent(source, home, aCircuit, flags, out reason); } // The simulators call this interface - public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason) + public bool LoginAgentToGrid(GridRegion source, AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason) { - return LoginAgentToGrid(aCircuit, gatekeeper, destination, null, out reason); + return LoginAgentToGrid(source, aCircuit, gatekeeper, destination, false, out reason); } - protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress) + protected override void PackData(OSDMap args, GridRegion source, AgentCircuitData aCircuit, GridRegion destination, uint flags) { - OSDMap args = null; - try - { - args = aCircuit.PackAgentCircuitData(); - } - catch (Exception e) - { - m_log.Debug("[USER AGENT CONNECTOR]: PackAgentCircuitData failed with exception: " + e.Message); - } - - // Add the input arguments - args["gatekeeper_serveruri"] = OSD.FromString(gatekeeper.ServerURI); - args["gatekeeper_host"] = OSD.FromString(gatekeeper.ExternalHostName); - args["gatekeeper_port"] = OSD.FromString(gatekeeper.HttpPort.ToString()); - args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); - args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); - args["destination_name"] = OSD.FromString(destination.RegionName); - args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); + base.PackData(args, source, aCircuit, destination, flags); + args["gatekeeper_serveruri"] = OSD.FromString(m_Gatekeeper.ServerURI); + args["gatekeeper_host"] = OSD.FromString(m_Gatekeeper.ExternalHostName); + args["gatekeeper_port"] = OSD.FromString(m_Gatekeeper.HttpPort.ToString()); args["destination_serveruri"] = OSD.FromString(destination.ServerURI); - - // 10/3/2010 - // I added the client_ip up to the regular AgentCircuitData, so this doesn't need to be here. - // This need cleaning elsewhere... - //if (ipaddress != null) - // args["client_ip"] = OSD.FromString(ipaddress.Address.ToString()); - - return args; } public void SetClientToken(UUID sessionID, string token) @@ -269,96 +162,111 @@ namespace OpenSim.Services.Connectors.Hypergrid // no-op } - public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt) + private Hashtable CallServer(string methodName, Hashtable hash) { - position = Vector3.UnitY; lookAt = Vector3.UnitY; - - Hashtable hash = new Hashtable(); - hash["userID"] = userID.ToString(); - IList paramList = new ArrayList(); paramList.Add(hash); - XmlRpcRequest request = new XmlRpcRequest("get_home_region", paramList); + XmlRpcRequest request = new XmlRpcRequest(methodName, paramList); + + // Send and get reply XmlRpcResponse response = null; try { response = request.Send(m_ServerURL, 10000); } - catch (Exception) + catch (Exception e) { - return null; + m_log.DebugFormat("[USER AGENT CONNECTOR]: {0} call to {1} failed: {2}", methodName, m_ServerURLHost, e.Message); + throw; } if (response.IsFault) { - return null; + throw new Exception(string.Format("[USER AGENT CONNECTOR]: {0} call to {1} returned an error: {2}", methodName, m_ServerURLHost, response.FaultString)); } hash = (Hashtable)response.Value; - //foreach (Object o in hash) - // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); - try + + if (hash == null) { - bool success = false; - Boolean.TryParse((string)hash["result"], out success); - if (success) - { - GridRegion region = new GridRegion(); + throw new Exception(string.Format("[USER AGENT CONNECTOR]: {0} call to {1} returned null", methodName, m_ServerURLHost)); + } - UUID.TryParse((string)hash["uuid"], out region.RegionID); - //m_log.Debug(">> HERE, uuid: " + region.RegionID); - int n = 0; - if (hash["x"] != null) - { - Int32.TryParse((string)hash["x"], out n); - region.RegionLocX = n; - //m_log.Debug(">> HERE, x: " + region.RegionLocX); - } - if (hash["y"] != null) - { - Int32.TryParse((string)hash["y"], out n); - region.RegionLocY = n; - //m_log.Debug(">> HERE, y: " + region.RegionLocY); - } - if (hash["region_name"] != null) - { - region.RegionName = (string)hash["region_name"]; - //m_log.Debug(">> HERE, name: " + region.RegionName); - } - if (hash["hostname"] != null) - region.ExternalHostName = (string)hash["hostname"]; - if (hash["http_port"] != null) - { - uint p = 0; - UInt32.TryParse((string)hash["http_port"], out p); - region.HttpPort = p; - } - if (hash.ContainsKey("server_uri") && hash["server_uri"] != null) - region.ServerURI = (string)hash["server_uri"]; + return hash; + } - if (hash["internal_port"] != null) - { - int p = 0; - Int32.TryParse((string)hash["internal_port"], out p); - region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p); - } - if (hash["position"] != null) - Vector3.TryParse((string)hash["position"], out position); - if (hash["lookAt"] != null) - Vector3.TryParse((string)hash["lookAt"], out lookAt); + public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt) + { + position = Vector3.UnitY; lookAt = Vector3.UnitY; - // Successful return - return region; - } + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + + hash = CallServer("get_home_region", hash); + + bool success; + if (!Boolean.TryParse((string)hash["result"], out success) || !success) + return null; + + GridRegion region = new GridRegion(); + UUID.TryParse((string)hash["uuid"], out region.RegionID); + //m_log.Debug(">> HERE, uuid: " + region.RegionID); + int n = 0; + if (hash["x"] != null) + { + Int32.TryParse((string)hash["x"], out n); + region.RegionLocX = n; + //m_log.Debug(">> HERE, x: " + region.RegionLocX); } - catch (Exception) + if (hash["y"] != null) { - return null; + Int32.TryParse((string)hash["y"], out n); + region.RegionLocY = n; + //m_log.Debug(">> HERE, y: " + region.RegionLocY); + } + if (hash["size_x"] != null) + { + Int32.TryParse((string)hash["size_x"], out n); + region.RegionSizeX = n; + //m_log.Debug(">> HERE, x: " + region.RegionLocX); } + if (hash["size_y"] != null) + { + Int32.TryParse((string)hash["size_y"], out n); + region.RegionSizeY = n; + //m_log.Debug(">> HERE, y: " + region.RegionLocY); + } + if (hash["region_name"] != null) + { + region.RegionName = (string)hash["region_name"]; + //m_log.Debug(">> HERE, name: " + region.RegionName); + } + if (hash["hostname"] != null) + region.ExternalHostName = (string)hash["hostname"]; + if (hash["http_port"] != null) + { + uint p = 0; + UInt32.TryParse((string)hash["http_port"], out p); + region.HttpPort = p; + } + if (hash.ContainsKey("server_uri") && hash["server_uri"] != null) + region.ServerURI = (string)hash["server_uri"]; - return null; + if (hash["internal_port"] != null) + { + int p = 0; + Int32.TryParse((string)hash["internal_port"], out p); + region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p); + } + if (hash["position"] != null) + Vector3.TryParse((string)hash["position"], out position); + if (hash["lookAt"] != null) + Vector3.TryParse((string)hash["lookAt"], out lookAt); + + // Successful return + return region; } public bool IsAgentComingHome(UUID sessionID, string thisGridExternalName) @@ -445,14 +353,14 @@ namespace OpenSim.Services.Connectors.Hypergrid } catch { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for StatusNotification", m_ServerURL); + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for StatusNotification", m_ServerURLHost); // reason = "Exception: " + e.Message; return friendsOnline; } if (response.IsFault) { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for StatusNotification returned an error: {1}", m_ServerURL, response.FaultString); + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for StatusNotification returned an error: {1}", m_ServerURLHost, response.FaultString); // reason = "XMLRPC Fault"; return friendsOnline; } @@ -464,7 +372,7 @@ namespace OpenSim.Services.Connectors.Hypergrid { if (hash == null) { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURLHost); // reason = "Internal error 1"; return friendsOnline; } @@ -517,14 +425,14 @@ namespace OpenSim.Services.Connectors.Hypergrid } catch { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetOnlineFriends", m_ServerURL); + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetOnlineFriends", m_ServerURLHost); // reason = "Exception: " + e.Message; return online; } if (response.IsFault) { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetOnlineFriends returned an error: {1}", m_ServerURL, response.FaultString); + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetOnlineFriends returned an error: {1}", m_ServerURLHost, response.FaultString); // reason = "XMLRPC Fault"; return online; } @@ -536,7 +444,7 @@ namespace OpenSim.Services.Connectors.Hypergrid { if (hash == null) { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURLHost); // reason = "Internal error 1"; return online; } @@ -567,51 +475,17 @@ namespace OpenSim.Services.Connectors.Hypergrid Hashtable hash = new Hashtable(); hash["userID"] = userID.ToString(); - IList paramList = new ArrayList(); - paramList.Add(hash); - - XmlRpcRequest request = new XmlRpcRequest("get_user_info", paramList); + hash = CallServer("get_user_info", hash); Dictionary info = new Dictionary(); - XmlRpcResponse response = null; - try - { - response = request.Send(m_ServerURL, 10000); - } - catch - { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetUserInfo", m_ServerURL); - return info; - } - if (response.IsFault) + foreach (object key in hash.Keys) { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetServerURLs returned an error: {1}", m_ServerURL, response.FaultString); - return info; - } - - hash = (Hashtable)response.Value; - try - { - if (hash == null) - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetUserInfo Got null response from {0}! THIS IS BAAAAD", m_ServerURL); - return info; - } - - // Here is the actual response - foreach (object key in hash.Keys) + if (hash[key] != null) { - if (hash[key] != null) - { - info.Add(key.ToString(), hash[key]); - } + info.Add(key.ToString(), hash[key]); } } - catch - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); - } return info; } @@ -621,60 +495,16 @@ namespace OpenSim.Services.Connectors.Hypergrid Hashtable hash = new Hashtable(); hash["userID"] = userID.ToString(); - IList paramList = new ArrayList(); - paramList.Add(hash); - - XmlRpcRequest request = new XmlRpcRequest("get_server_urls", paramList); -// string reason = string.Empty; - - // Send and get reply - Dictionary serverURLs = new Dictionary(); - XmlRpcResponse response = null; - try - { - response = request.Send(m_ServerURL, 10000); - } - catch - { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetServerURLs", m_ServerURL); -// reason = "Exception: " + e.Message; - return serverURLs; - } - - if (response.IsFault) - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetServerURLs returned an error: {1}", m_ServerURL, response.FaultString); -// reason = "XMLRPC Fault"; - return serverURLs; - } - - hash = (Hashtable)response.Value; - //foreach (Object o in hash) - // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); - try + hash = CallServer("get_server_urls", hash); + + Dictionary serverURLs = new Dictionary(); + foreach (object key in hash.Keys) { - if (hash == null) + if (key is string && ((string)key).StartsWith("SRV_") && hash[key] != null) { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetServerURLs Got null response from {0}! THIS IS BAAAAD", m_ServerURL); -// reason = "Internal error 1"; - return serverURLs; + string serverType = key.ToString().Substring(4); // remove "SRV_" + serverURLs.Add(serverType, hash[key].ToString()); } - - // Here is the actual response - foreach (object key in hash.Keys) - { - if (key is string && ((string)key).StartsWith("SRV_") && hash[key] != null) - { - string serverType = key.ToString().Substring(4); // remove "SRV_" - serverURLs.Add(serverType, hash[key].ToString()); - } - } - - } - catch - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); -// reason = "Exception: " + e.Message; } return serverURLs; @@ -685,55 +515,13 @@ namespace OpenSim.Services.Connectors.Hypergrid Hashtable hash = new Hashtable(); hash["userID"] = userID.ToString(); - IList paramList = new ArrayList(); - paramList.Add(hash); + hash = CallServer("locate_user", hash); - XmlRpcRequest request = new XmlRpcRequest("locate_user", paramList); -// string reason = string.Empty; - - // Send and get reply string url = string.Empty; - XmlRpcResponse response = null; - try - { - response = request.Send(m_ServerURL, 10000); - } - catch - { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for LocateUser", m_ServerURL); -// reason = "Exception: " + e.Message; - return url; - } - if (response.IsFault) - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for LocateUser returned an error: {1}", m_ServerURL, response.FaultString); -// reason = "XMLRPC Fault"; - return url; - } - - hash = (Hashtable)response.Value; - //foreach (Object o in hash) - // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); - try - { - if (hash == null) - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: LocateUser Got null response from {0}! THIS IS BAAAAD", m_ServerURL); -// reason = "Internal error 1"; - return url; - } - - // Here's the actual response - if (hash.ContainsKey("URL")) - url = hash["URL"].ToString(); - - } - catch - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response."); -// reason = "Exception: " + e.Message; - } + // Here's the actual response + if (hash.ContainsKey("URL")) + url = hash["URL"].ToString(); return url; } @@ -744,55 +532,13 @@ namespace OpenSim.Services.Connectors.Hypergrid hash["userID"] = userID.ToString(); hash["targetUserID"] = targetUserID.ToString(); - IList paramList = new ArrayList(); - paramList.Add(hash); - - XmlRpcRequest request = new XmlRpcRequest("get_uui", paramList); -// string reason = string.Empty; + hash = CallServer("get_uui", hash); - // Send and get reply string uui = string.Empty; - XmlRpcResponse response = null; - try - { - response = request.Send(m_ServerURL, 10000); - } - catch - { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetUUI", m_ServerURL); -// reason = "Exception: " + e.Message; - return uui; - } - - if (response.IsFault) - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetUUI returned an error: {1}", m_ServerURL, response.FaultString); -// reason = "XMLRPC Fault"; - return uui; - } - - hash = (Hashtable)response.Value; - //foreach (Object o in hash) - // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); - try - { - if (hash == null) - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetUUI Got null response from {0}! THIS IS BAAAAD", m_ServerURL); -// reason = "Internal error 1"; - return uui; - } - // Here's the actual response - if (hash.ContainsKey("UUI")) - uui = hash["UUI"].ToString(); - - } - catch - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetUUI response."); -// reason = "Exception: " + e.Message; - } + // Here's the actual response + if (hash.ContainsKey("UUI")) + uui = hash["UUI"].ToString(); return uui; } @@ -803,54 +549,17 @@ namespace OpenSim.Services.Connectors.Hypergrid hash["first"] = first; hash["last"] = last; - IList paramList = new ArrayList(); - paramList.Add(hash); + hash = CallServer("get_uuid", hash); - XmlRpcRequest request = new XmlRpcRequest("get_uuid", paramList); - // string reason = string.Empty; - - // Send and get reply - UUID uuid = UUID.Zero; - XmlRpcResponse response = null; - try - { - response = request.Send(m_ServerURL, 10000); - } - catch + if (!hash.ContainsKey("UUID")) { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetUUID", m_ServerURL); - // reason = "Exception: " + e.Message; - return uuid; + throw new Exception(string.Format("[USER AGENT CONNECTOR]: get_uuid call to {0} didn't return a UUID", m_ServerURLHost)); } - if (response.IsFault) - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetUUID returned an error: {1}", m_ServerURL, response.FaultString); - // reason = "XMLRPC Fault"; - return uuid; - } - - hash = (Hashtable)response.Value; - //foreach (Object o in hash) - // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); - try - { - if (hash == null) - { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetUUDI Got null response from {0}! THIS IS BAAAAD", m_ServerURL); - // reason = "Internal error 1"; - return uuid; - } - - // Here's the actual response - if (hash.ContainsKey("UUID")) - UUID.TryParse(hash["UUID"].ToString(), out uuid); - - } - catch + UUID uuid; + if (!UUID.TryParse(hash["UUID"].ToString(), out uuid)) { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on UUID response."); - // reason = "Exception: " + e.Message; + throw new Exception(string.Format("[USER AGENT CONNECTOR]: get_uuid call to {0} returned an invalid UUID: {1}", m_ServerURLHost, hash["UUID"].ToString())); } return uuid; @@ -858,7 +567,7 @@ namespace OpenSim.Services.Connectors.Hypergrid private bool GetBoolResponse(XmlRpcRequest request, out string reason) { - //m_log.Debug("[USER AGENT CONNECTOR]: GetBoolResponse from/to " + m_ServerURL); + //m_log.Debug("[USER AGENT CONNECTOR]: GetBoolResponse from/to " + m_ServerURLHost); XmlRpcResponse response = null; try { @@ -866,14 +575,14 @@ namespace OpenSim.Services.Connectors.Hypergrid } catch (Exception e) { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetBoolResponse", m_ServerURL); + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetBoolResponse", m_ServerURLHost); reason = "Exception: " + e.Message; return false; } if (response.IsFault) { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetBoolResponse returned an error: {1}", m_ServerURL, response.FaultString); + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetBoolResponse returned an error: {1}", m_ServerURLHost, response.FaultString); reason = "XMLRPC Fault"; return false; } @@ -885,7 +594,7 @@ namespace OpenSim.Services.Connectors.Hypergrid { if (hash == null) { - m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got null response from {0}! THIS IS BAAAAD", m_ServerURLHost); reason = "Internal error 1"; return false; } @@ -896,7 +605,7 @@ namespace OpenSim.Services.Connectors.Hypergrid else { reason = "Internal error 2"; - m_log.WarnFormat("[USER AGENT CONNECTOR]: response from {0} does not have expected key 'result'", m_ServerURL); + m_log.WarnFormat("[USER AGENT CONNECTOR]: response from {0} does not have expected key 'result'", m_ServerURLHost); } return success; diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs index dbce9f6..e19c23d 100644 --- a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs +++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs @@ -123,6 +123,7 @@ namespace OpenSim.Services.Connectors.InstantMessage gim["position_z"] = msg.Position.Z.ToString(); gim["region_id"] = msg.RegionID.ToString(); gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket, Base64FormattingOptions.None); + gim["region_id"] = new UUID(msg.RegionID).ToString(); return gim; } diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index 44f5e01..7cecd93 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -33,22 +33,37 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Framework.Communications; + +using OpenSim.Framework.Monitoring; using OpenSim.Services.Interfaces; using OpenSim.Server.Base; using OpenMetaverse; namespace OpenSim.Services.Connectors { - public class XInventoryServicesConnector : IInventoryService + public class XInventoryServicesConnector : BaseServiceConnector, IInventoryService { private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); + /// + /// Number of requests made to the remote inventory service. + /// + public int RequestsMade { get; private set; } + private string m_ServerURI = String.Empty; - private object m_Lock = new object(); + /// + /// Timeout for remote requests. + /// + /// + /// In this case, -1 is default timeout (100 seconds), not infinite. + /// + private int m_requestTimeoutSecs = -1; + + private const double CACHE_EXPIRATION_SECONDS = 20.0; + private static ExpiringCache m_ItemCache = new ExpiringCache(); public XInventoryServicesConnector() { @@ -60,20 +75,21 @@ namespace OpenSim.Services.Connectors } public XInventoryServicesConnector(IConfigSource source) + : base(source, "InventoryService") { Initialise(source); } public virtual void Initialise(IConfigSource source) { - IConfig assetConfig = source.Configs["InventoryService"]; - if (assetConfig == null) + IConfig config = source.Configs["InventoryService"]; + if (config == null) { m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini"); throw new Exception("Inventory connector init error"); } - string serviceURI = assetConfig.GetString("InventoryServerURI", + string serviceURI = config.GetString("InventoryServerURI", String.Empty); if (serviceURI == String.Empty) @@ -82,6 +98,45 @@ namespace OpenSim.Services.Connectors throw new Exception("Inventory connector init error"); } m_ServerURI = serviceURI; + + m_requestTimeoutSecs = config.GetInt("RemoteRequestTimeout", m_requestTimeoutSecs); + + StatsManager.RegisterStat( + new Stat( + "RequestsMade", + "Requests made", + "Number of requests made to the remove inventory service", + "requests", + "inventory", + serviceURI, + StatType.Pull, + MeasuresOfInterest.AverageChangeOverTime, + s => s.Value = RequestsMade, + StatVerbosity.Debug)); + } + + private bool CheckReturn(Dictionary ret) + { + if (ret == null) + return false; + + if (ret.Count == 0) + return false; + + if (ret.ContainsKey("RESULT")) + { + if (ret["RESULT"] is string) + { + bool result; + + if (bool.TryParse((string)ret["RESULT"], out result)) + return result; + + return false; + } + } + + return true; } public bool CreateUserInventory(UUID principalID) @@ -91,12 +146,7 @@ namespace OpenSim.Services.Connectors { "PRINCIPAL", principalID.ToString() } }); - if (ret == null) - return false; - if (ret.Count == 0) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public List GetInventorySkeleton(UUID principalID) @@ -106,9 +156,7 @@ namespace OpenSim.Services.Connectors { "PRINCIPAL", principalID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; Dictionary folders = (Dictionary)ret["FOLDERS"]; @@ -135,15 +183,13 @@ namespace OpenSim.Services.Connectors { "PRINCIPAL", principalID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; return BuildFolder((Dictionary)ret["folder"]); } - public InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) + public InventoryFolderBase GetFolderForType(UUID principalID, FolderType type) { Dictionary ret = MakeRequest("GETFOLDERFORTYPE", new Dictionary { @@ -151,9 +197,7 @@ namespace OpenSim.Services.Connectors { "TYPE", ((int)type).ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; return BuildFolder((Dictionary)ret["folder"]); @@ -164,7 +208,7 @@ namespace OpenSim.Services.Connectors InventoryCollection inventory = new InventoryCollection(); inventory.Folders = new List(); inventory.Items = new List(); - inventory.UserID = principalID; + inventory.OwnerID = principalID; try { @@ -174,20 +218,20 @@ namespace OpenSim.Services.Connectors { "FOLDER", folderID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; - Dictionary folders = - (Dictionary)ret["FOLDERS"]; - Dictionary items = - (Dictionary)ret["ITEMS"]; - - foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i - inventory.Folders.Add(BuildFolder((Dictionary)o)); - foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i - inventory.Items.Add(BuildItem((Dictionary)o)); + Dictionary folders = ret.ContainsKey("FOLDERS") ? + (Dictionary)ret["FOLDERS"] : null; + Dictionary items = ret.ContainsKey("ITEMS") ? + (Dictionary)ret["ITEMS"] : null; + + if (folders != null) + foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i + inventory.Folders.Add(BuildFolder((Dictionary)o)); + if (items != null) + foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i + inventory.Items.Add(BuildItem((Dictionary)o)); } catch (Exception e) { @@ -196,6 +240,87 @@ namespace OpenSim.Services.Connectors return inventory; } + + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] inventoryArr = new InventoryCollection[folderIDs.Length]; + // m_log.DebugFormat("[XXX]: In GetMultipleFoldersContent {0}", String.Join(",", folderIDs)); + try + { + Dictionary resultSet = MakeRequest("GETMULTIPLEFOLDERSCONTENT", + new Dictionary { + { "PRINCIPAL", principalID.ToString() }, + { "FOLDERS", String.Join(",", folderIDs) }, + { "COUNT", folderIDs.Length.ToString() } + }); + + if (!CheckReturn(resultSet)) + return null; + + int i = 0; + foreach (KeyValuePair kvp in resultSet) + { + InventoryCollection inventory = new InventoryCollection(); + if (kvp.Key.StartsWith("F_")) + { + UUID fid = UUID.Zero; + if (UUID.TryParse(kvp.Key.Substring(2), out fid) && fid == folderIDs[i]) + { + inventory.Folders = new List(); + inventory.Items = new List(); + + Dictionary ret = (Dictionary)kvp.Value; + + if (ret.ContainsKey("FID")) + { + if (!UUID.TryParse(ret["FID"].ToString(), out inventory.FolderID)) + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Could not parse folder id {0}", ret["FID"].ToString()); + } + else + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: FID key not present in response"); + + inventory.Version = -1; + if (ret.ContainsKey("VERSION")) + Int32.TryParse(ret["VERSION"].ToString(), out inventory.Version); + if (ret.ContainsKey("OWNER")) + UUID.TryParse(ret["OWNER"].ToString(), out inventory.OwnerID); + + //m_log.DebugFormat("[XXX]: Received {0} ({1}) {2} {3}", inventory.FolderID, fid, inventory.Version, inventory.OwnerID); + + Dictionary folders = + (Dictionary)ret["FOLDERS"]; + Dictionary items = + (Dictionary)ret["ITEMS"]; + + foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i + { + inventory.Folders.Add(BuildFolder((Dictionary)o)); + } + foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i + { + inventory.Items.Add(BuildItem((Dictionary)o)); + } + + inventoryArr[i] = inventory; + } + else + { + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Folder id does not match. Expected {0} got {1}", + folderIDs[i], fid); + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: {0} {1}", String.Join(",", folderIDs), String.Join(",", resultSet.Keys)); + } + + i += 1; + } + } + } + catch (Exception e) + { + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleFoldersContent: {0}", e.Message); + } + + return inventoryArr; + } public List GetFolderItems(UUID principalID, UUID folderID) { @@ -205,9 +330,7 @@ namespace OpenSim.Services.Connectors { "FOLDER", folderID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; Dictionary items = (Dictionary)ret["ITEMS"]; @@ -230,10 +353,7 @@ namespace OpenSim.Services.Connectors { "ID", folder.ID.ToString() } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool UpdateFolder(InventoryFolderBase folder) @@ -248,10 +368,7 @@ namespace OpenSim.Services.Connectors { "ID", folder.ID.ToString() } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool MoveFolder(InventoryFolderBase folder) @@ -263,10 +380,7 @@ namespace OpenSim.Services.Connectors { "PRINCIPAL", folder.Owner.ToString() } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool DeleteFolders(UUID principalID, List folderIDs) @@ -282,10 +396,7 @@ namespace OpenSim.Services.Connectors { "FOLDERS", slist } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool PurgeFolder(InventoryFolderBase folder) @@ -295,17 +406,18 @@ namespace OpenSim.Services.Connectors { "ID", folder.ID.ToString() } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool AddItem(InventoryItemBase item) { + if (item.Description == null) + item.Description = String.Empty; if (item.CreatorData == null) item.CreatorData = String.Empty; - Dictionary ret = MakeRequest("ADDITEM", + if (item.CreatorId == null) + item.CreatorId = String.Empty; + Dictionary ret = MakeRequest("ADDITEM", new Dictionary { { "AssetID", item.AssetID.ToString() }, { "AssetType", item.AssetType.ToString() }, @@ -330,10 +442,7 @@ namespace OpenSim.Services.Connectors { "CreationDate", item.CreationDate.ToString() } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool UpdateItem(InventoryItemBase item) @@ -365,10 +474,13 @@ namespace OpenSim.Services.Connectors { "CreationDate", item.CreationDate.ToString() } }); - if (ret == null) - return false; + bool result = CheckReturn(ret); + if (result) + { + m_ItemCache.AddOrUpdate(item.ID, item, CACHE_EXPIRATION_SECONDS); + } - return bool.Parse(ret["RESULT"].ToString()); + return result; } public bool MoveItems(UUID principalID, List items) @@ -389,10 +501,7 @@ namespace OpenSim.Services.Connectors { "DESTLIST", destlist } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public bool DeleteItems(UUID principalID, List itemIDs) @@ -408,14 +517,17 @@ namespace OpenSim.Services.Connectors { "ITEMS", slist } }); - if (ret == null) - return false; - - return bool.Parse(ret["RESULT"].ToString()); + return CheckReturn(ret); } public InventoryItemBase GetItem(InventoryItemBase item) { + InventoryItemBase retrieved = null; + if (m_ItemCache.TryGetValue(item.ID, out retrieved)) + { + return retrieved; + } + try { Dictionary ret = MakeRequest("GETITEM", @@ -423,19 +535,81 @@ namespace OpenSim.Services.Connectors { "ID", item.ID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; - return BuildItem((Dictionary)ret["item"]); + retrieved = BuildItem((Dictionary)ret["item"]); } catch (Exception e) { m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e); } - return null; + m_ItemCache.AddOrUpdate(item.ID, retrieved, CACHE_EXPIRATION_SECONDS); + + return retrieved; + } + + public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs) + { + //m_log.DebugFormat("[XXX]: In GetMultipleItems {0}", String.Join(",", itemIDs)); + + InventoryItemBase[] itemArr = new InventoryItemBase[itemIDs.Length]; + // Try to get them from the cache + List pending = new List(); + InventoryItemBase item = null; + int i = 0; + foreach (UUID id in itemIDs) + { + if (m_ItemCache.TryGetValue(id, out item)) + itemArr[i++] = item; + else + pending.Add(id); + } + + if (pending.Count == 0) // we're done, everything was in the cache + return itemArr; + + try + { + Dictionary resultSet = MakeRequest("GETMULTIPLEITEMS", + new Dictionary { + { "PRINCIPAL", principalID.ToString() }, + { "ITEMS", String.Join(",", pending.ToArray()) }, + { "COUNT", pending.Count.ToString() } + }); + + if (!CheckReturn(resultSet)) + { + if (i == 0) + return null; + else + return itemArr; + } + + // carry over index i where we left above + foreach (KeyValuePair kvp in resultSet) + { + InventoryCollection inventory = new InventoryCollection(); + if (kvp.Key.StartsWith("item_")) + { + if (kvp.Value is Dictionary) + { + item = BuildItem((Dictionary)kvp.Value); + m_ItemCache.AddOrUpdate(item.ID, item, CACHE_EXPIRATION_SECONDS); + itemArr[i++] = item; + } + else + itemArr[i++] = null; + } + } + } + catch (Exception e) + { + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleItems: {0}", e.Message); + } + + return itemArr; } public InventoryFolderBase GetFolder(InventoryFolderBase folder) @@ -447,9 +621,7 @@ namespace OpenSim.Services.Connectors { "ID", folder.ID.ToString() } }); - if (ret == null) - return null; - if (ret.Count == 0) + if (!CheckReturn(ret)) return null; return BuildFolder((Dictionary)ret["folder"]); @@ -469,7 +641,7 @@ namespace OpenSim.Services.Connectors { "PRINCIPAL", principalID.ToString() } }); - if (ret == null) + if (!CheckReturn(ret)) return null; List items = new List(); @@ -488,51 +660,22 @@ namespace OpenSim.Services.Connectors { "ASSET", assetID.ToString() } }); + // We cannot use CheckReturn() here because valid values for RESULT are "false" (in the case of request failure) or an int if (ret == null) return 0; - return int.Parse(ret["RESULT"].ToString()); - } - - public InventoryCollection GetUserInventory(UUID principalID) - { - InventoryCollection inventory = new InventoryCollection(); - inventory.Folders = new List(); - inventory.Items = new List(); - inventory.UserID = principalID; - - try + if (ret.ContainsKey("RESULT")) { - Dictionary ret = MakeRequest("GETUSERINVENTORY", - new Dictionary { - { "PRINCIPAL", principalID.ToString() } - }); - - if (ret == null) - return null; - if (ret.Count == 0) - return null; - - Dictionary folders = - (Dictionary)ret["FOLDERS"]; - Dictionary items = - (Dictionary)ret["ITEMS"]; + if (ret["RESULT"] is string) + { + int intResult; - foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i - inventory.Folders.Add(BuildFolder((Dictionary)o)); - foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i - inventory.Items.Add(BuildItem((Dictionary)o)); + if (int.TryParse ((string)ret["RESULT"], out intResult)) + return intResult; + } } - catch (Exception e) - { - m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetUserInventory: ", e); - } - - return inventory; - } - public void GetUserInventory(UUID principalID, InventoryReceiptCallback callback) - { + return 0; } public bool HasInventoryForUser(UUID principalID) @@ -545,13 +688,19 @@ namespace OpenSim.Services.Connectors private Dictionary MakeRequest(string method, Dictionary sendData) { - sendData["METHOD"] = method; + // Add "METHOD" as the first key in the dictionary. This ensures that it will be + // visible even when using partial logging ("debug http all 5"). + Dictionary temp = sendData; + sendData = new Dictionary{ { "METHOD", method } }; + foreach (KeyValuePair kvp in temp) + sendData.Add(kvp.Key, kvp.Value); + + RequestsMade++; - string reply = string.Empty; - lock (m_Lock) - reply = SynchronousRestFormsRequester.MakeRequest("POST", - m_ServerURI + "/xinventory", - ServerUtils.BuildQueryString(sendData)); + string reply + = SynchronousRestFormsRequester.MakeRequest( + "POST", m_ServerURI + "/xinventory", + ServerUtils.BuildQueryString(sendData), m_requestTimeoutSecs, m_Auth); Dictionary replyData = ServerUtils.ParseXmlResponse( reply); @@ -619,4 +768,4 @@ namespace OpenSim.Services.Connectors return item; } } -} \ No newline at end of file +} diff --git a/OpenSim/Services/Connectors/Land/LandServicesConnector.cs b/OpenSim/Services/Connectors/Land/LandServicesConnector.cs index 30a73a4..034c42e 100644 --- a/OpenSim/Services/Connectors/Land/LandServicesConnector.cs +++ b/OpenSim/Services/Connectors/Land/LandServicesConnector.cs @@ -33,7 +33,7 @@ using System.IO; using System.Reflection; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Communications; + using OpenSim.Services.Interfaces; using OpenMetaverse; using Nwc.XmlRpc; @@ -78,7 +78,7 @@ namespace OpenSim.Services.Connectors try { uint xpos = 0, ypos = 0; - Utils.LongToUInts(regionHandle, out xpos, out ypos); + Util.RegionHandleToWorldLoc(regionHandle, out xpos, out ypos); GridRegion info = m_GridService.GetRegionByPosition(scopeID, (int)xpos, (int)ypos); if (info != null) // just to be sure { diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs index 30bfb70..c91ed84 100644 --- a/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs +++ b/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs @@ -35,7 +35,8 @@ using System.Reflection; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Framework.Communications; + +using OpenSim.Framework.ServiceAuth; using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenMetaverse; @@ -43,7 +44,7 @@ using OpenMetaverse.StructuredData; namespace OpenSim.Services.Connectors { - public class MapImageServicesConnector : IMapImageService + public class MapImageServicesConnector : BaseServiceConnector, IMapImageService { private static readonly ILog m_log = LogManager.GetLogger( @@ -84,26 +85,26 @@ namespace OpenSim.Services.Connectors } m_ServerURI = serviceURI; m_ServerURI = serviceURI.TrimEnd('/'); + base.Initialise(source, "MapImageService"); } - public bool AddMapTile(int x, int y, byte[] jpgData, out string reason) + public bool RemoveMapTile(int x, int y, out string reason) { reason = string.Empty; int tickstart = Util.EnvironmentTickCount(); Dictionary sendData = new Dictionary(); sendData["X"] = x.ToString(); sendData["Y"] = y.ToString(); - sendData["TYPE"] = "image/jpeg"; - sendData["DATA"] = Convert.ToBase64String(jpgData); string reqString = ServerUtils.BuildQueryString(sendData); - string uri = m_ServerURI + "/map"; + string uri = m_ServerURI + "/removemap"; try { string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -114,7 +115,7 @@ namespace OpenSim.Services.Connectors } else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure")) { - m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Registration failed: {0}", replyData["Message"].ToString()); + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Delete failed: {0}", replyData["Message"].ToString()); reason = replyData["Message"].ToString(); return false; } @@ -142,6 +143,72 @@ namespace OpenSim.Services.Connectors { // This just dumps a warning for any operation that takes more than 100 ms int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: map tile deleted in {0}ms", tickdiff); + } + + return false; + } + + public bool AddMapTile(int x, int y, byte[] jpgData, out string reason) + { + reason = string.Empty; + int tickstart = Util.EnvironmentTickCount(); + Dictionary sendData = new Dictionary(); + sendData["X"] = x.ToString(); + sendData["Y"] = y.ToString(); + sendData["TYPE"] = "image/jpeg"; + sendData["DATA"] = Convert.ToBase64String(jpgData); + + string reqString = ServerUtils.BuildQueryString(sendData); + string uri = m_ServerURI + "/map"; + + try + { + string reply = SynchronousRestFormsRequester.MakeRequest("POST", + uri, + reqString, + m_Auth); + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "success")) + { + return true; + } + else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure")) + { + reason = string.Format("Map post to {0} failed: {1}", uri, replyData["Message"].ToString()); + m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason); + + return false; + } + else if (!replyData.ContainsKey("Result")) + { + reason = string.Format("Reply data from {0} does not contain result field", uri); + m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason); + } + else + { + reason = string.Format("Unexpected result {0} from {1}" + replyData["Result"].ToString(), uri); + m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason); + } + } + else + { + reason = string.Format("Map post received null reply from {0}", uri); + m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason); + } + } + catch (Exception e) + { + reason = string.Format("Exception when posting to map server at {0}: {1}", uri, e.Message); + m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason); + } + finally + { + // This just dumps a warning for any operation that takes more than 100 ms + int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); m_log.DebugFormat("[MAP IMAGE CONNECTOR]: map tile uploaded in {0}ms", tickdiff); } diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs index 7429293..925364a 100644 --- a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs +++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs @@ -35,7 +35,7 @@ using System.Reflection; using System.Text; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Communications; + using OpenSim.Services.Interfaces; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -69,7 +69,7 @@ namespace OpenSim.Services.Connectors public virtual GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion) { uint x = 0, y = 0; - Utils.LongToUInts(regionHandle, out x, out y); + Util.RegionHandleToWorldLoc(regionHandle, out x, out y); GridRegion regInfo = m_GridService.GetRegionByPosition(thisRegion.ScopeID, (int)x, (int)y); if ((regInfo != null) && // Don't remote-call this instance; that's a startup hickup @@ -97,9 +97,9 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.WarnFormat( - "[NEIGHBOUR SERVICE CONNCTOR]: Unable to parse uri {0} to send HelloNeighbour from {1} to {2}. Exception {3}{4}", - uri, thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace); + m_log.Warn(string.Format( + "[NEIGHBOUR SERVICES CONNECTOR]: Unable to parse uri {0} to send HelloNeighbour from {1} to {2}. Exception {3} ", + uri, thisRegion.RegionName, region.RegionName, e.Message), e); return false; } @@ -116,9 +116,9 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.WarnFormat( - "[NEIGHBOUR SERVICE CONNCTOR]: PackRegionInfoData failed for HelloNeighbour from {0} to {1}. Exception {2}{3}", - thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace); + m_log.Warn(string.Format( + "[NEIGHBOUR SERVICES CONNECTOR]: PackRegionInfoData failed for HelloNeighbour from {0} to {1}. Exception {2} ", + thisRegion.RegionName, region.RegionName, e.Message), e); return false; } @@ -136,9 +136,9 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.WarnFormat( - "[NEIGHBOUR SERVICE CONNCTOR]: Exception thrown on serialization of HelloNeighbour from {0} to {1}. Exception {2}{3}", - thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace); + m_log.Warn(string.Format( + "[NEIGHBOUR SERVICES CONNECTOR]: Exception thrown on serialization of HelloNeighbour from {0} to {1}. Exception {2} ", + thisRegion.RegionName, region.RegionName, e.Message), e); return false; } @@ -153,53 +153,53 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.WarnFormat( - "[NEIGHBOUR SERVICE CONNCTOR]: Unable to send HelloNeighbour from {0} to {1}. Exception {2}{3}", - thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace); + m_log.Warn(string.Format( + "[NEIGHBOUR SERVICES CONNECTOR]: Unable to send HelloNeighbour from {0} to {1} (uri {2}). Exception {3} ", + thisRegion.RegionName, region.RegionName, uri, e.Message), e); return false; } finally { if (os != null) - os.Close(); + os.Dispose(); } // Let's wait for the response //m_log.Info("[REST COMMS]: Waiting for a reply after DoHelloNeighbourCall"); - StreamReader sr = null; try { - WebResponse webResponse = helloNeighbourRequest.GetResponse(); - if (webResponse == null) + using (WebResponse webResponse = helloNeighbourRequest.GetResponse()) { - m_log.DebugFormat( - "[REST COMMS]: Null reply on DoHelloNeighbourCall post from {0} to {1}", - thisRegion.RegionName, region.RegionName); + if (webResponse == null) + { + m_log.DebugFormat( + "[NEIGHBOUR SERVICES CONNECTOR]: Null reply on DoHelloNeighbourCall post from {0} to {1}", + thisRegion.RegionName, region.RegionName); + } + + using (Stream s = webResponse.GetResponseStream()) + { + using (StreamReader sr = new StreamReader(s)) + { + //reply = sr.ReadToEnd().Trim(); + sr.ReadToEnd().Trim(); + //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply); + } + } } - - sr = new StreamReader(webResponse.GetResponseStream()); - //reply = sr.ReadToEnd().Trim(); - sr.ReadToEnd().Trim(); - //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply); - } catch (Exception e) { - m_log.WarnFormat( - "[NEIGHBOUR SERVICE CONNCTOR]: Exception on reply of DoHelloNeighbourCall from {0} back to {1}. Exception {2}{3}", - region.RegionName, thisRegion.RegionName, e.Message, e.StackTrace); + m_log.Warn(string.Format( + "[NEIGHBOUR SERVICES CONNECTOR]: Exception on reply of DoHelloNeighbourCall from {0} back to {1}. Exception {2} ", + region.RegionName, thisRegion.RegionName, e.Message), e); return false; } - finally - { - if (sr != null) - sr.Close(); - } return true; } } -} \ No newline at end of file +} diff --git a/OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs b/OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs index f7d8c53..b7e95c4 100644 --- a/OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs +++ b/OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs @@ -32,7 +32,8 @@ using System.IO; using System.Reflection; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Communications; + +using OpenSim.Framework.ServiceAuth; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Server.Base; @@ -40,7 +41,7 @@ using OpenMetaverse; namespace OpenSim.Services.Connectors { - public class PresenceServicesConnector : IPresenceService + public class PresenceServicesConnector : BaseServiceConnector, IPresenceService { private static readonly ILog m_log = LogManager.GetLogger( @@ -80,6 +81,8 @@ namespace OpenSim.Services.Connectors throw new Exception("Presence connector init error"); } m_ServerURI = serviceURI; + + base.Initialise(source, "PresenceService"); } @@ -104,7 +107,8 @@ namespace OpenSim.Services.Connectors { string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -149,7 +153,8 @@ namespace OpenSim.Services.Connectors { string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -193,7 +198,8 @@ namespace OpenSim.Services.Connectors { string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -238,7 +244,8 @@ namespace OpenSim.Services.Connectors { string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply != string.Empty) { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -283,7 +290,8 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply == null || (reply != null && reply == string.Empty)) { m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgent received null or empty reply"); @@ -293,6 +301,7 @@ namespace OpenSim.Services.Connectors catch (Exception e) { m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message); + return null; } Dictionary replyData = ServerUtils.ParseXmlResponse(reply); @@ -327,7 +336,8 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply == null || (reply != null && reply == string.Empty)) { m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received null or empty reply"); diff --git a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs index bfb681b..c581a59 100644 --- a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs index 95e4bab..cd4781d 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs @@ -69,7 +69,7 @@ namespace OpenSim.Services.Connectors.SimianGrid Util.FireAndForget(delegate(object o) { m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); - }); + }, null, "SimianActivityDetector.SetLastPositionOnMakeRootAgent"); } public void OnNewClient(IClientAPI client) @@ -94,7 +94,7 @@ namespace OpenSim.Services.Connectors.SimianGrid Util.FireAndForget(delegate(object o) { m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); - }); + }, null, "SimianActivityDetector.SetLastPositionOnEnteringNewParcel"); } } } \ No newline at end of file diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 63a32e7..9ad4a7a 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.IO; using System.Net; using System.Reflection; @@ -122,7 +123,7 @@ namespace OpenSim.Services.Connectors.SimianGrid m_Enabled = true; } - #region IAssetService +#region IAssetService public AssetBase Get(string id) { @@ -140,8 +141,9 @@ namespace OpenSim.Services.Connectors.SimianGrid return asset; } - return GetRemote(id); + return SimianGetOperation(id); } + public AssetBase GetCached(string id) { @@ -164,8 +166,6 @@ namespace OpenSim.Services.Connectors.SimianGrid throw new InvalidOperationException(); } - AssetMetadata metadata = null; - // Cache fetch if (m_cache != null) { @@ -174,50 +174,18 @@ namespace OpenSim.Services.Connectors.SimianGrid return asset.Metadata; } - Uri url; - - // Determine if id is an absolute URL or a grid-relative UUID - if (!Uri.TryCreate(id, UriKind.Absolute, out url)) - url = new Uri(m_serverUrl + id); - - try - { - HttpWebRequest request = UntrustedHttpWebRequest.Create(url); - request.Method = "HEAD"; - - using (WebResponse response = request.GetResponse()) - { - using (Stream responseStream = response.GetResponseStream()) - { - // Create the metadata object - metadata = new AssetMetadata(); - metadata.ContentType = response.ContentType; - metadata.ID = id; - - UUID uuid; - if (UUID.TryParse(id, out uuid)) - metadata.FullID = uuid; - - string lastModifiedStr = response.Headers.Get("Last-Modified"); - if (!String.IsNullOrEmpty(lastModifiedStr)) - { - DateTime lastModified; - if (DateTime.TryParse(lastModifiedStr, out lastModified)) - metadata.CreationDate = lastModified; - } - } - } - } - catch (Exception ex) - { - m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset HEAD from " + url + " failed: " + ex.Message); - } - - return metadata; + // return GetRemoteMetadata(id); + return SimianGetMetadataOperation(id); } - + public byte[] GetData(string id) { + if (String.IsNullOrEmpty(m_serverUrl)) + { + m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured"); + throw new InvalidOperationException(); + } + AssetBase asset = Get(id); if (asset != null) @@ -255,14 +223,34 @@ namespace OpenSim.Services.Connectors.SimianGrid Util.FireAndForget( delegate(object o) { - AssetBase asset = GetRemote(id); + AssetBase asset = SimianGetOperation(id); handler(id, sender, asset); - } + }, null, "SimianAssetServiceConnector.GetFromService" ); return true; } + public bool[] AssetsExist(string[] ids) + { + if (String.IsNullOrEmpty(m_serverUrl)) + { + m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured"); + throw new InvalidOperationException(); + } + + bool[] exist = new bool[ids.Length]; + + for (int i = 0; i < ids.Length; i++) + { + AssetMetadata metadata = GetMetadata(ids[i]); + if (metadata != null) + exist[i] = true; + } + + return exist; + } + /// /// Creates a new asset /// @@ -278,7 +266,6 @@ namespace OpenSim.Services.Connectors.SimianGrid } bool storedInCache = false; - string errorMessage = null; // AssetID handling if (String.IsNullOrEmpty(asset.ID) || asset.ID == ZeroID) @@ -307,80 +294,9 @@ namespace OpenSim.Services.Connectors.SimianGrid return asset.ID; } - // Distinguish public and private assets - bool isPublic = true; - switch ((AssetType)asset.Type) - { - case AssetType.CallingCard: - case AssetType.Gesture: - case AssetType.LSLBytecode: - case AssetType.LSLText: - isPublic = false; - break; - } - - // Make sure ContentType is set - if (String.IsNullOrEmpty(asset.Metadata.ContentType)) - asset.Metadata.ContentType = SLUtil.SLAssetTypeToContentType(asset.Type); - - // Build the remote storage request - List postParameters = new List() - { - new MultipartForm.Parameter("AssetID", asset.FullID.ToString()), - new MultipartForm.Parameter("CreatorID", asset.Metadata.CreatorID), - new MultipartForm.Parameter("Temporary", asset.Temporary ? "1" : "0"), - new MultipartForm.Parameter("Public", isPublic ? "1" : "0"), - new MultipartForm.File("Asset", asset.Name, asset.Metadata.ContentType, asset.Data) - }; - - // Make the remote storage request - try - { - // Simian does not require the asset ID to be in the URL because it's in the post data. - // By appending it to the URL also, we allow caching proxies (squid) to invalidate asset URLs - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl + asset.FullID.ToString()); - - HttpWebResponse response = MultipartForm.Post(request, postParameters); - using (Stream responseStream = response.GetResponseStream()) - { - string responseStr = null; - - try - { - responseStr = responseStream.GetStreamString(); - OSD responseOSD = OSDParser.Deserialize(responseStr); - if (responseOSD.Type == OSDType.Map) - { - OSDMap responseMap = (OSDMap)responseOSD; - if (responseMap["Success"].AsBoolean()) - return asset.ID; - else - errorMessage = "Upload failed: " + responseMap["Message"].AsString(); - } - else - { - errorMessage = "Response format was invalid:\n" + responseStr; - } - } - catch (Exception ex) - { - if (!String.IsNullOrEmpty(responseStr)) - errorMessage = "Failed to parse the response:\n" + responseStr; - else - errorMessage = "Failed to retrieve the response: " + ex.Message; - } - } - } - catch (WebException ex) - { - errorMessage = ex.Message; - } - - m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to store asset \"{0}\" ({1}, {2}): {3}", - asset.Name, asset.ID, asset.Metadata.ContentType, errorMessage); - return null; + return SimianStoreOperation(asset); } - + /// /// Update an asset's content /// @@ -390,11 +306,17 @@ namespace OpenSim.Services.Connectors.SimianGrid /// public bool UpdateContent(string id, byte[] data) { + if (String.IsNullOrEmpty(m_serverUrl)) + { + m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured"); + throw new InvalidOperationException(); + } + AssetBase asset = Get(id); if (asset == null) { - m_log.Warn("[SIMIAN ASSET CONNECTOR]: Failed to fetch asset " + id + " for updating"); + m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to fetch asset {0} for updating", id); return false; } @@ -417,83 +339,347 @@ namespace OpenSim.Services.Connectors.SimianGrid throw new InvalidOperationException(); } - //string errorMessage = String.Empty; - string url = m_serverUrl + id; - if (m_cache != null) m_cache.Expire(id); + return SimianDeleteOperation(id); + } + +#endregion IAssetService + +#region SimianOperations + /// + /// Invokes the xRemoveAsset operation on the simian server to delete an asset + /// + /// + /// + private bool SimianDeleteOperation(string id) + { try { - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); - request.Method = "DELETE"; + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "xRemoveAsset" }, + { "AssetID", id } + }; - using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) + OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs); + if (! response["Success"].AsBoolean()) { - if (response.StatusCode != HttpStatusCode.NoContent) - { - m_log.Warn("[SIMIAN ASSET CONNECTOR]: Unexpected response when deleting asset " + url + ": " + - response.StatusCode + " (" + response.StatusDescription + ")"); - } + m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to delete asset; {0}",response["Message"].AsString()); + return false; } - + return true; + } catch (Exception ex) { - m_log.Warn("[SIMIAN ASSET CONNECTOR]: Failed to delete asset " + id + " from the asset service: " + ex.Message); - return false; + m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to delete asset {0}; {1}", id, ex.Message); } - } - #endregion IAssetService + return false; + } - private AssetBase GetRemote(string id) + /// + /// Invokes the xAddAsset operation on the simian server to create or update an asset + /// + /// + /// + private string SimianStoreOperation(AssetBase asset) { - AssetBase asset = null; - Uri url; + try + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "xAddAsset" }, + { "ContentType", asset.Metadata.ContentType }, + { "EncodedData", Convert.ToBase64String(asset.Data) }, + { "AssetID", asset.FullID.ToString() }, + { "CreatorID", asset.Metadata.CreatorID }, + { "Temporary", asset.Temporary ? "1" : "0" }, + { "Name", asset.Name } + }; + + OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs); + if (! response["Success"].AsBoolean()) + { + m_log.WarnFormat("[SIMIAN ASSET CONNECTOR] failed to store asset; {0}",response["Message"].AsString()); + return null; + } - // Determine if id is an absolute URL or a grid-relative UUID - if (!Uri.TryCreate(id, UriKind.Absolute, out url)) - url = new Uri(m_serverUrl + id); + // asset.ID is always set before calling this function + return asset.ID; + + } + catch (Exception ex) + { + m_log.ErrorFormat("[SIMIAN ASSET CONNECTOR] failed to store asset; {0}",ex.Message); + } + + return null; + } - try + /// + /// Invokes the xGetAsset operation on the simian server to get data associated with an asset + /// + /// + /// + private AssetBase SimianGetOperation(string id) + { + try { - HttpWebRequest request = UntrustedHttpWebRequest.Create(url); + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "xGetAsset" }, + { "ID", id } + }; - using (WebResponse response = request.GetResponse()) + OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs); + if (! response["Success"].AsBoolean()) { - using (Stream responseStream = response.GetResponseStream()) - { - string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty; - - // Create the asset object - asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID); - - UUID assetID; - if (UUID.TryParse(id, out assetID)) - asset.FullID = assetID; - - // Grab the asset data from the response stream - using (MemoryStream stream = new MemoryStream()) - { - responseStream.CopyStream(stream, Int32.MaxValue); - asset.Data = stream.ToArray(); - } - } + m_log.WarnFormat("[SIMIAN ASSET CONNECTOR] Failed to get asset; {0}",response["Message"].AsString()); + return null; } + + AssetBase asset = new AssetBase(); - // Cache store - if (m_cache != null && asset != null) - m_cache.Cache(asset); + asset.ID = id; + asset.Name = String.Empty; + asset.Metadata.ContentType = response["ContentType"].AsString(); // this will also set the asset Type property + asset.CreatorID = response["CreatorID"].AsString(); + asset.Data = System.Convert.FromBase64String(response["EncodedData"].AsString()); + asset.Local = false; + asset.Temporary = response["Temporary"]; return asset; } catch (Exception ex) { - m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message); - return null; + m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to retrieve asset {0}; {1}", id, ex.Message); + } + + return null; + } + + /// + /// Invokes the xGetAssetMetadata operation on the simian server to retrieve metadata for an asset + /// This operation is generally used to determine if an asset exists in the database + /// + /// + /// + private AssetMetadata SimianGetMetadataOperation(string id) + { + try + { + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "xGetAssetMetadata" }, + { "ID", id } + }; + + OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs); + if (! response["Success"].AsBoolean()) + { + // this is not really an error, this call is used to test existence + // m_log.DebugFormat("[SIMIAN ASSET CONNECTOR] Failed to get asset metadata; {0}",response["Message"].AsString()); + return null; + } + + AssetMetadata metadata = new AssetMetadata(); + metadata.ID = id; + metadata.ContentType = response["ContentType"].AsString(); + metadata.CreatorID = response["CreatorID"].AsString(); + metadata.Local = false; + metadata.Temporary = response["Temporary"]; + + string lastModifiedStr = response["Last-Modified"].AsString(); + if (! String.IsNullOrEmpty(lastModifiedStr)) + { + DateTime lastModified; + if (DateTime.TryParse(lastModifiedStr, out lastModified)) + metadata.CreationDate = lastModified; + } + + return metadata; + } + catch (Exception ex) + { + m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to get asset metadata; {0}", ex.Message); } + + return null; } +#endregion + + // private AssetMetadata GetRemoteMetadata(string id) + // { + // Uri url; + // AssetMetadata metadata = null; + + // // Determine if id is an absolute URL or a grid-relative UUID + // if (!Uri.TryCreate(id, UriKind.Absolute, out url)) + // url = new Uri(m_serverUrl + id); + + // try + // { + // HttpWebRequest request = UntrustedHttpWebRequest.Create(url); + // request.Method = "HEAD"; + + // using (WebResponse response = request.GetResponse()) + // { + // using (Stream responseStream = response.GetResponseStream()) + // { + // // Create the metadata object + // metadata = new AssetMetadata(); + // metadata.ContentType = response.ContentType; + // metadata.ID = id; + + // UUID uuid; + // if (UUID.TryParse(id, out uuid)) + // metadata.FullID = uuid; + + // string lastModifiedStr = response.Headers.Get("Last-Modified"); + // if (!String.IsNullOrEmpty(lastModifiedStr)) + // { + // DateTime lastModified; + // if (DateTime.TryParse(lastModifiedStr, out lastModified)) + // metadata.CreationDate = lastModified; + // } + // } + // } + // } + // catch (Exception ex) + // { + // m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset HEAD from " + url + " failed: " + ex.Message); + // } + + // return metadata; + // } + + // private AssetBase GetRemote(string id) + // { + // AssetBase asset = null; + // Uri url; + + // // Determine if id is an absolute URL or a grid-relative UUID + // if (!Uri.TryCreate(id, UriKind.Absolute, out url)) + // url = new Uri(m_serverUrl + id); + + // try + // { + // HttpWebRequest request = UntrustedHttpWebRequest.Create(url); + + // using (WebResponse response = request.GetResponse()) + // { + // using (Stream responseStream = response.GetResponseStream()) + // { + // string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty; + + // // Create the asset object + // asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID); + + // UUID assetID; + // if (UUID.TryParse(id, out assetID)) + // asset.FullID = assetID; + + // // Grab the asset data from the response stream + // using (MemoryStream stream = new MemoryStream()) + // { + // responseStream.CopyStream(stream, Int32.MaxValue); + // asset.Data = stream.ToArray(); + // } + // } + // } + + // // Cache store + // if (m_cache != null && asset != null) + // m_cache.Cache(asset); + + // return asset; + // } + // catch (Exception ex) + // { + // m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message); + // return null; + // } + // } + + // private string StoreRemote(AssetBase asset) + // { + // // Distinguish public and private assets + // bool isPublic = true; + // switch ((AssetType)asset.Type) + // { + // case AssetType.CallingCard: + // case AssetType.Gesture: + // case AssetType.LSLBytecode: + // case AssetType.LSLText: + // isPublic = false; + // break; + // } + + // string errorMessage = null; + + // // Build the remote storage request + // List postParameters = new List() + // { + // new MultipartForm.Parameter("AssetID", asset.FullID.ToString()), + // new MultipartForm.Parameter("CreatorID", asset.Metadata.CreatorID), + // new MultipartForm.Parameter("Temporary", asset.Temporary ? "1" : "0"), + // new MultipartForm.Parameter("Public", isPublic ? "1" : "0"), + // new MultipartForm.File("Asset", asset.Name, asset.Metadata.ContentType, asset.Data) + // }; + + // // Make the remote storage request + // try + // { + // // Simian does not require the asset ID to be in the URL because it's in the post data. + // // By appending it to the URL also, we allow caching proxies (squid) to invalidate asset URLs + // HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl + asset.FullID.ToString()); + + // using (HttpWebResponse response = MultipartForm.Post(request, postParameters)) + // { + // using (Stream responseStream = response.GetResponseStream()) + // { + // string responseStr = null; + + // try + // { + // responseStr = responseStream.GetStreamString(); + // OSD responseOSD = OSDParser.Deserialize(responseStr); + // if (responseOSD.Type == OSDType.Map) + // { + // OSDMap responseMap = (OSDMap)responseOSD; + // if (responseMap["Success"].AsBoolean()) + // return asset.ID; + // else + // errorMessage = "Upload failed: " + responseMap["Message"].AsString(); + // } + // else + // { + // errorMessage = "Response format was invalid:\n" + responseStr; + // } + // } + // catch (Exception ex) + // { + // if (!String.IsNullOrEmpty(responseStr)) + // errorMessage = "Failed to parse the response:\n" + responseStr; + // else + // errorMessage = "Failed to retrieve the response: " + ex.Message; + // } + // } + // } + // } + // catch (WebException ex) + // { + // errorMessage = ex.Message; + // } + + // m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to store asset \"{0}\" ({1}, {2}): {3}", + // asset.Name, asset.ID, asset.Metadata.ContentType, errorMessage); + + // return null; + // } } } diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs index 6603f6e..3bd11d9 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs @@ -110,7 +110,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "UserID", principalID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["Identities"] is OSDArray) { bool md5hashFound = false; @@ -153,7 +153,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "SessionID", token } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean()) { return true; @@ -175,7 +175,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "UserID", principalID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean()) { return true; @@ -198,7 +198,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "UserID", principalID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["User"] is OSDMap) { OSDMap userMap = (OSDMap)response["User"]; @@ -218,7 +218,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "UserID", principalID.ToString() } }; - response = WebUtil.PostToService(m_serverUrl, requestArgs); + response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -297,7 +297,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "UserID", userID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean()) return response["SessionID"].AsUUID().ToString(); else diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs index 841bfa0..a397740 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs @@ -122,7 +122,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "UserID", userID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean()) { OSDMap map = null; @@ -168,7 +168,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "LLPackedAppearance", OSDParser.SerializeJsonString(map) } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (! success) @@ -189,7 +189,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "UserID", userID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean()) { OSDMap map = null; @@ -306,7 +306,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "LLAttachments", OSDParser.SerializeJsonString(items) } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs b/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs new file mode 100644 index 0000000..764e71f --- /dev/null +++ b/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs @@ -0,0 +1,180 @@ +/* + * 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 OpenSimulator 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.Reflection; +using System.IO; +using System.Web; + +using log4net; +using Nini.Config; +using Mono.Addins; + +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Services.Connectors.SimianGrid +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianExternalCapsModule")] + public class SimianExternalCapsModule : INonSharedRegionModule, IExternalCapsModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private bool m_enabled = true; + private Scene m_scene; + private String m_simianURL; + +#region IRegionModule Members + + public string Name + { + get { return this.GetType().Name; } + } + + public void Initialise(IConfigSource config) + { + try + { + IConfig m_config; + + if ((m_config = config.Configs["SimianExternalCaps"]) != null) + { + m_enabled = m_config.GetBoolean("Enabled", m_enabled); + if ((m_config = config.Configs["SimianGrid"]) != null) + { + m_simianURL = m_config.GetString("SimianServiceURL"); + if (String.IsNullOrEmpty(m_simianURL)) + { + //m_log.DebugFormat("[SimianGrid] service URL is not defined"); + m_enabled = false; + return; + } + } + } + else + m_enabled = false; + } + catch (Exception e) + { + m_log.ErrorFormat("[SimianExternalCaps] initialization error: {0}",e.Message); + return; + } + } + + public void PostInitialise() { } + public void Close() { } + + public void AddRegion(Scene scene) + { + if (! m_enabled) + return; + + m_scene = scene; + m_scene.RegisterModuleInterface(this); + } + + public void RemoveRegion(Scene scene) + { + if (! m_enabled) + return; + + m_scene.EventManager.OnRegisterCaps -= RegisterCapsEventHandler; + m_scene.EventManager.OnDeregisterCaps -= DeregisterCapsEventHandler; + } + + public void RegionLoaded(Scene scene) + { + if (! m_enabled) + return; + + m_scene.EventManager.OnRegisterCaps += RegisterCapsEventHandler; + m_scene.EventManager.OnDeregisterCaps += DeregisterCapsEventHandler; + } + + public Type ReplaceableInterface + { + get { return null; } + } + +#endregion + +#region IExternalCapsModule + // Eg http://grid.sciencesim.com/GridPublic/%CAP%/%OP%/" + public bool RegisterExternalUserCapsHandler(UUID agentID, Caps caps, String capName, String urlSkel) + { + UUID cap = UUID.Random(); + + // Call to simian to register the cap we generated + // NameValueCollection requestArgs = new NameValueCollection + // { + // { "RequestMethod", "AddCapability" }, + // { "Resource", "user" }, + // { "Expiration", 0 }, + // { "OwnerID", agentID.ToString() }, + // { "CapabilityID", cap.ToString() } + // }; + + // OSDMap response = SimianGrid.PostToService(m_simianURL, requestArgs); + + Dictionary subs = new Dictionary(); + subs["%OP%"] = capName; + subs["%USR%"] = agentID.ToString(); + subs["%CAP%"] = cap.ToString(); + subs["%SIM%"] = m_scene.RegionInfo.RegionID.ToString(); + + caps.RegisterHandler(capName,ExpandSkeletonURL(urlSkel,subs)); + return true; + } + +#endregion + +#region EventHandlers + public void RegisterCapsEventHandler(UUID agentID, Caps caps) { } + public void DeregisterCapsEventHandler(UUID agentID, Caps caps) { } +#endregion + + private String ExpandSkeletonURL(String urlSkel, Dictionary subs) + { + String result = urlSkel; + + foreach (KeyValuePair kvp in subs) + { + result = result.Replace(kvp.Key,kvp.Value); + } + + return result; + } + } +} \ No newline at end of file diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs index 7422d94..9a8164c 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -153,7 +153,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Value", flags.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -180,7 +180,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Key", friend } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -200,7 +200,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Type", "Friend" } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) { return (OSDArray)response["Entries"]; @@ -221,7 +221,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Type", "Friend" } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) { return (OSDArray)response["Entries"]; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs index 847319c..a35d749 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs @@ -26,8 +26,122 @@ */ using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Reflection; +using log4net; using Mono.Addins; using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenMetaverse; +using OpenMetaverse.StructuredData; -[assembly: Addin("SimianGrid", "1.0")] -[assembly: AddinDependency("OpenSim", "0.5")] +[assembly: Addin("SimianGrid", OpenSim.VersionInfo.VersionNumber)] +[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] + +namespace OpenSim.Services.Connectors.SimianGrid +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianExternalCapsModule")] + public class SimianGrid : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IConfig m_config = null; + + private String m_simianURL; + +#region IRegionModule Members + + public string Name + { + get { return this.GetType().Name; } + } + + public void Initialise(IConfigSource config) + { + try + { + m_config = config.Configs["SimianGrid"]; + + if (m_config != null) + { + m_simianURL = m_config.GetString("SimianServiceURL"); + if (String.IsNullOrEmpty(m_simianURL)) + { + // m_log.DebugFormat("[SimianGrid] service URL is not defined"); + return; + } + + InitialiseSimCap(); + SimulatorCapability = SimulatorCapability.Trim(); + m_log.InfoFormat("[SimianExternalCaps] using {0} as simulator capability",SimulatorCapability); + } + } + catch (Exception e) + { + m_log.ErrorFormat("[SimianExternalCaps] initialization error: {0}",e.Message); + return; + } + } + + public void PostInitialise() { } + public void Close() { } + public void AddRegion(Scene scene) { } + public void RemoveRegion(Scene scene) { } + public void RegionLoaded(Scene scene) { } + + public Type ReplaceableInterface + { + get { return null; } + } + + /// + /// Try a variety of methods for finding the simian simulator capability; first check the + /// configuration itself, then look for a file that contains the cap, then finally look + /// for an environment variable that contains it. + /// + private void InitialiseSimCap() + { + if (m_config.Contains("SimulatorCapability")) + { + SimulatorCapability = m_config.GetString("SimulatorCapability"); + return; + } + + if (m_config.Contains("SimulatorCapabilityFile")) + { + String filename = m_config.GetString("SimulatorCapabilityFile"); + if (System.IO.File.Exists(filename)) + { + SimulatorCapability = System.IO.File.ReadAllText(filename); + return; + } + } + + if (m_config.Contains("SimulatorCapabilityVariable")) + { + String envname = m_config.GetString("SimulatorCapabilityVariable"); + String envvalue = System.Environment.GetEnvironmentVariable(envname); + if (envvalue != null) + { + SimulatorCapability = envvalue; + return; + } + } + + m_log.WarnFormat("[SimianExternalCaps] no method specified for simulator capability"); + } + +#endregion + + public static String SimulatorCapability = UUID.Zero.ToString(); + public static OSDMap PostToService(string url, NameValueCollection data) + { + data["cap"] = SimulatorCapability; + return WebUtil.PostToService(url, data); + } + } +} \ No newline at end of file diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs index 93fdae3..8375c95 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.Reflection; using System.Net; using System.IO; @@ -43,7 +44,8 @@ using OpenSim.Region.Framework.Scenes; using OpenMetaverse; using OpenMetaverse.StructuredData; -namespace OpenSim.Region.OptionalModules.Simian +//namespace OpenSim.Region.OptionalModules.Simian +namespace OpenSim.Services.Connectors.SimianGrid { /// /// @@ -179,7 +181,6 @@ namespace OpenSim.Region.OptionalModules.Simian m_log.DebugFormat("[SIMIAN MAPTILE]: upload maptile for {0}",scene.RegionInfo.RegionName); // Create a PNG map tile and upload it to the AddMapTile API - byte[] pngData = Utils.EmptyBytes; IMapImageGenerator tileGenerator = scene.RequestModuleInterface(); if (tileGenerator == null) { @@ -187,76 +188,79 @@ namespace OpenSim.Region.OptionalModules.Simian return; } - using (Image mapTile = tileGenerator.CreateMapTile()) - { - using (MemoryStream stream = new MemoryStream()) - { - mapTile.Save(stream, ImageFormat.Png); - pngData = stream.ToArray(); - } - } - - List postParameters = new List() - { - new MultipartForm.Parameter("X", scene.RegionInfo.RegionLocX.ToString()), - new MultipartForm.Parameter("Y", scene.RegionInfo.RegionLocY.ToString()), - new MultipartForm.File("Tile", "tile.png", "image/png", pngData) - }; - - string errorMessage = null; - int tickstart = Util.EnvironmentTickCount(); - - // Make the remote storage request - try + using (Bitmap mapTile = tileGenerator.CreateMapTile()) { - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl); - request.Timeout = 20000; - request.ReadWriteTimeout = 5000; - - using (HttpWebResponse response = MultipartForm.Post(request, postParameters)) + if (mapTile != null) { - using (Stream responseStream = response.GetResponseStream()) + // If the region/maptile is legacy sized, just upload the one tile like it has always been done + if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize) { - string responseStr = responseStream.GetStreamString(); - OSD responseOSD = OSDParser.Deserialize(responseStr); - if (responseOSD.Type == OSDType.Map) + ConvertAndUploadMaptile(mapTile, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY); + } + else + { + // For larger regions (varregion) we must cut the region image into legacy sized + // pieces since that is how the maptile system works. + // Note the assumption that varregions are always a multiple of legacy size. + for (uint xx = 0; xx < mapTile.Width; xx += Constants.RegionSize) { - OSDMap responseMap = (OSDMap)responseOSD; - if (responseMap["Success"].AsBoolean()) - return; + for (uint yy = 0; yy < mapTile.Height; yy += Constants.RegionSize) + { + // Images are addressed from the upper left corner so have to do funny + // math to pick out the sub-tile since regions are numbered from + // the lower left. + Rectangle rect = new Rectangle( + (int)xx, + mapTile.Height - (int)yy - (int)Constants.RegionSize, + (int)Constants.RegionSize, (int)Constants.RegionSize); - errorMessage = "Upload failed: " + responseMap["Message"].AsString(); - } - else - { - errorMessage = "Response format was invalid:\n" + responseStr; + using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat)) + { + uint locX = scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize); + uint locY = scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize); + + ConvertAndUploadMaptile(subMapTile, locX, locY); + } + } } } } - } - catch (WebException we) - { - errorMessage = we.Message; - if (we.Status == WebExceptionStatus.ProtocolError) + else { - HttpWebResponse webResponse = (HttpWebResponse)we.Response; - errorMessage = String.Format("[{0}] {1}", - webResponse.StatusCode,webResponse.StatusDescription); + m_log.WarnFormat("[SIMIAN MAPTILE] Tile image generation failed"); } } - catch (Exception ex) + + } + + /// + /// + /// + private void ConvertAndUploadMaptile(Image mapTile, uint locX, uint locY) + { + //m_log.DebugFormat("[SIMIAN MAPTILE]: upload maptile for location {0}, {1}", locX, locY); + + byte[] pngData = Utils.EmptyBytes; + using (MemoryStream stream = new MemoryStream()) { - errorMessage = ex.Message; + mapTile.Save(stream, ImageFormat.Png); + pngData = stream.ToArray(); } - finally + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "xAddMapTile" }, + { "X", locX.ToString() }, + { "Y", locY.ToString() }, + { "ContentType", "image/png" }, + { "EncodedData", System.Convert.ToBase64String(pngData) } + }; + + OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs); + if (! response["Success"].AsBoolean()) { - // This just dumps a warning for any operation that takes more than 100 ms - int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); - m_log.DebugFormat("[SIMIAN MAPTILE]: map tile uploaded in {0}ms",tickdiff); + m_log.WarnFormat("[SIMIAN MAPTILE] failed to store map tile; {0}",response["Message"].AsString()); } - - m_log.WarnFormat("[SIMIAN MAPTILE]: Failed to store {0} byte tile for {1}: {2}", - pngData.Length, scene.RegionInfo.RegionName, errorMessage); } } } \ No newline at end of file diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index 038a4bf..b031f21 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -101,7 +101,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public string RegisterRegion(UUID scopeID, GridRegion regionInfo) { Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); - Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); + Vector3d maxPosition = minPosition + new Vector3d(regionInfo.RegionSizeX, regionInfo.RegionSizeY, Constants.RegionHeight); OSDMap extraData = new OSDMap { @@ -129,7 +129,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "ExtraData", OSDParser.SerializeJsonString(extraData) } }; - OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); + OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs); if (response["Success"].AsBoolean()) return String.Empty; else @@ -145,7 +145,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Enabled", "0" } }; - OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); + OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -156,15 +156,15 @@ namespace OpenSim.Services.Connectors.SimianGrid public List GetNeighbours(UUID scopeID, UUID regionID) { - const int NEIGHBOR_RADIUS = 128; - GridRegion region = GetRegionByUUID(scopeID, regionID); + int NEIGHBOR_RADIUS = Math.Max(region.RegionSizeX, region.RegionSizeY) / 2; + if (region != null) { List regions = GetRegionRange(scopeID, - region.RegionLocX - NEIGHBOR_RADIUS, region.RegionLocX + (int)Constants.RegionSize + NEIGHBOR_RADIUS, - region.RegionLocY - NEIGHBOR_RADIUS, region.RegionLocY + (int)Constants.RegionSize + NEIGHBOR_RADIUS); + region.RegionLocX - NEIGHBOR_RADIUS, region.RegionLocX + region.RegionSizeX + NEIGHBOR_RADIUS, + region.RegionLocY - NEIGHBOR_RADIUS, region.RegionLocY + region.RegionSizeY + NEIGHBOR_RADIUS); for (int i = 0; i < regions.Count; i++) { @@ -192,7 +192,7 @@ namespace OpenSim.Services.Connectors.SimianGrid // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region with uuid {0}",regionID.ToString()); - OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); + OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs); if (response["Success"].AsBoolean()) { // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] uuid request successful {0}",response["Name"].AsString()); @@ -220,7 +220,7 @@ namespace OpenSim.Services.Connectors.SimianGrid // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request grid at {0}",position.ToString()); - OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); + OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs); if (response["Success"].AsBoolean()) { // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] position request successful {0}",response["Name"].AsString()); @@ -229,7 +229,7 @@ namespace OpenSim.Services.Connectors.SimianGrid else { // m_log.InfoFormat("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region at {0},{1}", - // x / Constants.RegionSize, y / Constants.RegionSize); + // Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y)); return null; } } @@ -261,7 +261,7 @@ namespace OpenSim.Services.Connectors.SimianGrid // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions with name {0}",name); - OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); + OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs); if (response["Success"].AsBoolean()) { // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] found regions with name {0}",name); @@ -299,7 +299,7 @@ namespace OpenSim.Services.Connectors.SimianGrid //m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions by range {0} to {1}",minPosition.ToString(),maxPosition.ToString()); - OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); + OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs); if (response["Success"].AsBoolean()) { OSDArray array = response["Scenes"] as OSDArray; @@ -330,6 +330,12 @@ namespace OpenSim.Services.Connectors.SimianGrid return new List(0); } + public List GetDefaultHypergridRegions(UUID scopeID) + { + // TODO: Allow specifying the default grid location + return GetDefaultRegions(scopeID); + } + public List GetFallbackRegions(UUID scopeID, int x, int y) { GridRegion defRegion = GetNearestRegion(new Vector3d(x, y, 0.0), true); @@ -350,7 +356,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Enabled", "1" } }; - OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); + OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs); if (response["Success"].AsBoolean()) { // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] found regions with name {0}",name); @@ -380,7 +386,7 @@ namespace OpenSim.Services.Connectors.SimianGrid m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region flags for {0}",regionID.ToString()); - OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); + OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs); if (response["Success"].AsBoolean()) { OSDMap extraData = response["ExtraData"] as OSDMap; @@ -396,6 +402,13 @@ namespace OpenSim.Services.Connectors.SimianGrid return -1; } } + + public Dictionary GetExtraFeatures() + { + /// See SimulatorFeaturesModule - Need to get map, search and destination guide + Dictionary extraFeatures = new Dictionary(); + return extraFeatures; + } #endregion IGridService @@ -410,7 +423,7 @@ namespace OpenSim.Services.Connectors.SimianGrid if (onlyEnabled) requestArgs["Enabled"] = "1"; - OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); + OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs); if (response["Success"].AsBoolean()) { return ResponseToGridRegion(response); @@ -437,9 +450,13 @@ namespace OpenSim.Services.Connectors.SimianGrid region.RegionName = response["Name"].AsString(); Vector3d minPosition = response["MinPosition"].AsVector3d(); + Vector3d maxPosition = response["MaxPosition"].AsVector3d(); region.RegionLocX = (int)minPosition.X; region.RegionLocY = (int)minPosition.Y; - + + region.RegionSizeX = (int)maxPosition.X - (int)minPosition.X; + region.RegionSizeY = (int)maxPosition.Y - (int)minPosition.Y; + if ( ! extraData["HyperGrid"] ) { Uri httpAddress = response["Address"].AsUri(); region.ExternalHostName = httpAddress.Host; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index a391275..e793420 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -38,12 +38,14 @@ using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; +using PermissionMask = OpenSim.Framework.PermissionMask; namespace OpenSim.Services.Connectors.SimianGrid { /// /// Permissions bitflags /// + /* [Flags] public enum PermissionMask : uint { @@ -55,6 +57,7 @@ namespace OpenSim.Services.Connectors.SimianGrid Damage = 1 << 20, All = 0x7FFFFFFF } + */ /// /// Connects avatar inventories to the SimianGrid backend @@ -71,6 +74,9 @@ namespace OpenSim.Services.Connectors.SimianGrid // private object m_gestureSyncRoot = new object(); private bool m_Enabled = false; + private const double CACHE_EXPIRATION_SECONDS = 20.0; + private static ExpiringCache m_ItemCache; + #region ISharedRegionModule public Type ReplaceableInterface { get { return null; } } @@ -96,6 +102,9 @@ namespace OpenSim.Services.Connectors.SimianGrid url = url + '/'; m_serverUrl = url; + if (m_ItemCache == null) + m_ItemCache = new ExpiringCache(); + } public void Initialise(IConfigSource source) @@ -129,6 +138,8 @@ namespace OpenSim.Services.Connectors.SimianGrid { m_userServerUrl = serviceUrl; m_Enabled = true; + if (m_ItemCache == null) + m_ItemCache = new ExpiringCache(); } } } @@ -153,7 +164,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "OwnerID", userID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -179,7 +190,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "ChildrenOnly", "0" } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["Items"] is OSDArray) { OSDArray items = (OSDArray)response["Items"]; @@ -194,37 +205,6 @@ namespace OpenSim.Services.Connectors.SimianGrid } /// - /// Synchronous inventory fetch. - /// - /// - /// - [Obsolete] - public InventoryCollection GetUserInventory(UUID userID) - { - m_log.Error("[SIMIAN INVENTORY CONNECTOR]: Obsolete GetUserInventory called for " + userID); - - InventoryCollection inventory = new InventoryCollection(); - inventory.UserID = userID; - inventory.Folders = new List(); - inventory.Items = new List(); - - return inventory; - } - - /// - /// Request the inventory for a user. This is an asynchronous operation that will call the callback when the - /// inventory has been received - /// - /// - /// - [Obsolete] - public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) - { - m_log.Error("[SIMIAN INVENTORY CONNECTOR]: Obsolete GetUserInventory called for " + userID); - callback(new List(0), new List(0)); - } - - /// /// Retrieve the root inventory folder for the given user. /// /// @@ -241,7 +221,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "ChildrenOnly", "1" } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["Items"] is OSDArray) { OSDArray items = (OSDArray)response["Items"]; @@ -260,7 +240,7 @@ namespace OpenSim.Services.Connectors.SimianGrid /// /// /// - public InventoryFolderBase GetFolderForType(UUID userID, AssetType type) + public InventoryFolderBase GetFolderForType(UUID userID, FolderType type) { string contentType = SLUtil.SLAssetTypeToContentType((int)type); @@ -271,7 +251,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "OwnerID", userID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["Folder"] is OSDMap) { OSDMap folder = (OSDMap)response["Folder"]; @@ -299,6 +279,10 @@ namespace OpenSim.Services.Connectors.SimianGrid /// public InventoryItemBase GetItem(InventoryItemBase item) { + InventoryItemBase retrieved = null; + if (m_ItemCache.TryGetValue(item.ID, out retrieved)) + return retrieved; + NameValueCollection requestArgs = new NameValueCollection { { "RequestMethod", "GetInventoryNode" }, @@ -309,7 +293,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "ChildrenOnly", "1" } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["Items"] is OSDArray) { List items = GetItemsFromResponse((OSDArray)response["Items"]); @@ -320,7 +304,11 @@ namespace OpenSim.Services.Connectors.SimianGrid for (int i = 0; i < items.Count; i++) { if (items[i].ID == item.ID) - return items[i]; + { + retrieved = items[i]; + m_ItemCache.AddOrUpdate(item.ID, retrieved, CACHE_EXPIRATION_SECONDS); + return retrieved; + } } } } @@ -329,6 +317,21 @@ namespace OpenSim.Services.Connectors.SimianGrid return null; } + public InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs) + { + InventoryItemBase[] result = new InventoryItemBase[itemIDs.Length]; + int i = 0; + InventoryItemBase item = new InventoryItemBase(); + item.Owner = principalID; + foreach (UUID id in itemIDs) + { + item.ID = id; + result[i++] = GetItem(item); + } + + return result; + } + /// /// Get a folder, given by its UUID /// @@ -346,7 +349,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "ChildrenOnly", "1" } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["Items"] is OSDArray) { OSDArray items = (OSDArray)response["Items"]; @@ -368,7 +371,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public InventoryCollection GetFolderContent(UUID userID, UUID folderID) { InventoryCollection inventory = new InventoryCollection(); - inventory.UserID = userID; + inventory.OwnerID = userID; NameValueCollection requestArgs = new NameValueCollection { @@ -380,7 +383,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "ChildrenOnly", "1" } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["Items"] is OSDArray) { OSDArray items = (OSDArray)response["Items"]; @@ -399,6 +402,18 @@ namespace OpenSim.Services.Connectors.SimianGrid return inventory; } + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + { + invColl[i++] = GetFolderContent(principalID, fid); + } + + return invColl; + } + /// /// Gets the items inside a folder /// @@ -408,7 +423,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public List GetFolderItems(UUID userID, UUID folderID) { InventoryCollection inventory = new InventoryCollection(); - inventory.UserID = userID; + inventory.OwnerID = userID; NameValueCollection requestArgs = new NameValueCollection { @@ -420,7 +435,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "ChildrenOnly", "1" } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["Items"] is OSDArray) { OSDArray items = (OSDArray)response["Items"]; @@ -451,7 +466,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "ContentType", SLUtil.SLAssetTypeToContentType(folder.Type) } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -515,7 +530,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "ItemID", itemID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -543,7 +558,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "FolderID", folder.ID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -565,7 +580,9 @@ namespace OpenSim.Services.Connectors.SimianGrid // A folder of UUID.Zero means we need to find the most appropriate home for this item if (item.Folder == UUID.Zero) { - InventoryFolderBase folder = GetFolderForType(item.Owner, (AssetType)item.AssetType); + InventoryFolderBase folder = null; + if (Enum.IsDefined(typeof(FolderType), (sbyte)item.AssetType)) + folder = GetFolderForType(item.Owner, (FolderType)item.AssetType); if (folder != null && folder.ID != UUID.Zero) item.Folder = folder.ID; else @@ -620,7 +637,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "ExtraData", OSDParser.SerializeJsonString(extraData) } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -844,7 +861,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Items", String.Join(",", itemIDs) } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -882,7 +899,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "UserID", userID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_userServerUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs); if (response["Success"].AsBoolean()) { OSDMap user = response["User"] as OSDMap; @@ -913,7 +930,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "Gestures", OSDParser.SerializeJsonString(gestures) } }; - OSDMap response = WebUtil.PostToService(m_userServerUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs); if (!response["Success"].AsBoolean()) { m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to save active gestures for " + userID + ": " + diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs index 854bea4..211b775 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs @@ -65,7 +65,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public void PostInitialise() { } public void Close() { } - public SimianPresenceServiceConnector() { m_activityDetector = new SimianActivityDetector(this); } + public SimianPresenceServiceConnector() { } public string Name { get { return "SimianPresenceServiceConnector"; } } public void AddRegion(Scene scene) { @@ -121,6 +121,7 @@ namespace OpenSim.Services.Connectors.SimianGrid if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) serviceUrl = serviceUrl + '/'; m_serverUrl = serviceUrl; + m_activityDetector = new SimianActivityDetector(this); m_Enabled = true; } } @@ -137,17 +138,18 @@ namespace OpenSim.Services.Connectors.SimianGrid userID, sessionID, secureSessionID); NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "AddSession" }, - { "UserID", userID.ToString() } - }; + { + { "RequestMethod", "AddSession" }, + { "UserID", userID.ToString() } + }; + if (sessionID != UUID.Zero) { requestArgs["SessionID"] = sessionID.ToString(); requestArgs["SecureSessionID"] = secureSessionID.ToString(); } - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -158,15 +160,15 @@ namespace OpenSim.Services.Connectors.SimianGrid public bool LogoutAgent(UUID sessionID) { -// m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID); + // m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID); NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "RemoveSession" }, - { "SessionID", sessionID.ToString() } - }; + { + { "RequestMethod", "RemoveSession" }, + { "SessionID", sessionID.ToString() } + }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -177,15 +179,15 @@ namespace OpenSim.Services.Connectors.SimianGrid public bool LogoutRegionAgents(UUID regionID) { -// m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for all agents in region " + regionID); + // m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for all agents in region " + regionID); NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "RemoveSessions" }, - { "SceneID", regionID.ToString() } - }; + { + { "RequestMethod", "RemoveSessions" }, + { "SceneID", regionID.ToString() } + }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -202,49 +204,46 @@ namespace OpenSim.Services.Connectors.SimianGrid public PresenceInfo GetAgent(UUID sessionID) { -// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent with sessionID " + sessionID); - - NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "GetSession" }, - { "SessionID", sessionID.ToString() } - }; - - OSDMap sessionResponse = WebUtil.PostToService(m_serverUrl, requestArgs); - if (sessionResponse["Success"].AsBoolean()) + OSDMap sessionResponse = GetSessionDataFromSessionID(sessionID); + if (sessionResponse == null) { - UUID userID = sessionResponse["UserID"].AsUUID(); - m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); - - requestArgs = new NameValueCollection - { - { "RequestMethod", "GetUser" }, - { "UserID", userID.ToString() } - }; - - OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs); - if (userResponse["Success"].AsBoolean()) - return ResponseToPresenceInfo(sessionResponse, userResponse); - else - m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString()); + m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session {0}: {1}",sessionID.ToString(),sessionResponse["Message"].AsString()); + return null; } - else + + UUID userID = sessionResponse["UserID"].AsUUID(); + OSDMap userResponse = GetUserData(userID); + if (userResponse == null) { - m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session " + sessionID + ": " + sessionResponse["Message"].AsString()); + m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}: {1}",userID.ToString(),userResponse["Message"].AsString()); + return null; } - return null; + return ResponseToPresenceInfo(sessionResponse); } public PresenceInfo[] GetAgents(string[] userIDs) { - List presences = new List(userIDs.Length); + List presences = new List(); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetSessions" }, + { "UserIDList", String.Join(",",userIDs) } + }; - for (int i = 0; i < userIDs.Length; i++) + OSDMap sessionListResponse = SimianGrid.PostToService(m_serverUrl, requestArgs); + if (! sessionListResponse["Success"].AsBoolean()) { - UUID userID; - if (UUID.TryParse(userIDs[i], out userID) && userID != UUID.Zero) - presences.AddRange(GetSessions(userID)); + m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve sessions: {0}",sessionListResponse["Message"].AsString()); + return null; + } + + OSDArray sessionList = sessionListResponse["Sessions"] as OSDArray; + for (int i = 0; i < sessionList.Count; i++) + { + OSDMap sessionInfo = sessionList[i] as OSDMap; + presences.Add(ResponseToPresenceInfo(sessionInfo)); } return presences.ToArray(); @@ -262,7 +261,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) { -// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Logging out user " + userID); + // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Logging out user " + userID); // Remove the session to mark this user offline if (!LogoutAgent(sessionID)) @@ -270,13 +269,13 @@ namespace OpenSim.Services.Connectors.SimianGrid // Save our last position as user data NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "AddUserData" }, - { "UserID", userID.ToString() }, - { "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) } - }; + { + { "RequestMethod", "AddUserData" }, + { "UserID", userID.ToString() }, + { "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) } + }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -287,16 +286,16 @@ namespace OpenSim.Services.Connectors.SimianGrid public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) { -// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID); + // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID); NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "AddUserData" }, - { "UserID", userID.ToString() }, - { "HomeLocation", SerializeLocation(regionID, position, lookAt) } - }; + { + { "RequestMethod", "AddUserData" }, + { "UserID", userID.ToString() }, + { "HomeLocation", SerializeLocation(regionID, position, lookAt) } + }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -312,24 +311,19 @@ namespace OpenSim.Services.Connectors.SimianGrid public GridUserInfo GetGridUserInfo(string user) { -// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent " + user); + // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent " + user); UUID userID = new UUID(user); -// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); + OSDMap userResponse = GetUserData(userID); - NameValueCollection requestArgs = new NameValueCollection + if (userResponse == null) { - { "RequestMethod", "GetUser" }, - { "UserID", userID.ToString() } - }; + m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}", userID); + } - OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs); - if (userResponse["Success"].AsBoolean()) - return ResponseToGridUserInfo(userResponse); - else - m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString()); + // Note that ResponseToGridUserInfo properly checks for and returns a null if passed a null. + return ResponseToGridUserInfo(userResponse); - return null; } #endregion @@ -338,67 +332,51 @@ namespace OpenSim.Services.Connectors.SimianGrid private OSDMap GetUserData(UUID userID) { -// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); + // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "GetUser" }, - { "UserID", userID.ToString() } - }; + { + { "RequestMethod", "GetUser" }, + { "UserID", userID.ToString() } + }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["User"] is OSDMap) return response; - else - m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + response["Message"].AsString()); + m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}; {1}",userID.ToString(),response["Message"].AsString()); return null; } - private List GetSessions(UUID userID) + private OSDMap GetSessionDataFromSessionID(UUID sessionID) { - List presences = new List(1); - - OSDMap userResponse = GetUserData(userID); - if (userResponse != null) - { -// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting sessions for " + userID); - - NameValueCollection requestArgs = new NameValueCollection + NameValueCollection requestArgs = new NameValueCollection { - { "RequestMethod", "GetSession" }, - { "UserID", userID.ToString() } + { "RequestMethod", "GetSession" }, + { "SessionID", sessionID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); - if (response["Success"].AsBoolean()) - { - PresenceInfo presence = ResponseToPresenceInfo(response, userResponse); - if (presence != null) - presences.Add(presence); - } -// else -// { -// m_log.Debug("[SIMIAN PRESENCE CONNECTOR]: No session returned for " + userID + ": " + response["Message"].AsString()); -// } - } + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); + if (response["Success"].AsBoolean()) + return response; - return presences; + m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session data for {0}; {1}",sessionID.ToString(),response["Message"].AsString()); + return null; } private bool UpdateSession(UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) { // Save our current location as session data NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "UpdateSession" }, - { "SessionID", sessionID.ToString() }, - { "SceneID", regionID.ToString() }, - { "ScenePosition", lastPosition.ToString() }, - { "SceneLookAt", lastLookAt.ToString() } - }; + { + { "RequestMethod", "UpdateSession" }, + { "SessionID", sessionID.ToString() }, + { "SceneID", regionID.ToString() }, + { "ScenePosition", lastPosition.ToString() }, + { "SceneLookAt", lastLookAt.ToString() } + }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -407,7 +385,7 @@ namespace OpenSim.Services.Connectors.SimianGrid return success; } - private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse, OSDMap userResponse) + private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse) { if (sessionResponse == null) return null; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs index bd8069f..8fc766d 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs @@ -392,7 +392,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "UserID", client.AgentId.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); string email = response["Email"].AsString(); if (!response["Success"].AsBoolean()) @@ -425,7 +425,7 @@ namespace OpenSim.Services.Connectors.SimianGrid estate.EstateID, admin.Name); estate.EstateOwner = admin.PrincipalID; - estate.Save(); + scene.EstateDataService.StoreEstateSettings(estate); } else { @@ -443,7 +443,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { key, OSDParser.SerializeJsonString(value) } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (!success) @@ -462,7 +462,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "UserID", userID.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean() && response["User"] is OSDMap) { return (OSDMap)response["User"]; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs index 6e32b3a..698c4c0 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs @@ -165,7 +165,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "NameQuery", query } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean()) { OSDArray array = response["Users"] as OSDArray; @@ -191,6 +191,11 @@ namespace OpenSim.Services.Connectors.SimianGrid return accounts; } + public void InvalidateCache(UUID userID) + { + m_accountCache.Remove(userID); + } + public bool StoreUserAccount(UserAccount data) { // m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Storing user account for " + data.Name); @@ -204,7 +209,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "AccessLevel", data.UserLevel.ToString() } }; - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean()) { @@ -219,7 +224,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "UserTitle", data.UserTitle } }; - response = WebUtil.PostToService(m_serverUrl, requestArgs); + response = SimianGrid.PostToService(m_serverUrl, requestArgs); bool success = response["Success"].AsBoolean(); if (success) @@ -252,7 +257,7 @@ namespace OpenSim.Services.Connectors.SimianGrid string lookupValue = (requestArgs.Count > 1) ? requestArgs[1] : "(Unknown)"; // m_log.DebugFormat("[SIMIAN ACCOUNT CONNECTOR]: Looking up user account with query: " + lookupValue); - OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); + OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean()) { OSDMap user = response["User"] as OSDMap; diff --git a/OpenSim/Services/Connectors/Simulation/EstateDataService.cs b/OpenSim/Services/Connectors/Simulation/EstateDataService.cs deleted file mode 100644 index cdcdecf..0000000 --- a/OpenSim/Services/Connectors/Simulation/EstateDataService.cs +++ /dev/null @@ -1,139 +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 OpenSimulator 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.Generic; -using OpenMetaverse; -using log4net; -using Mono.Addins; -using Nini.Config; -using System.Reflection; -using OpenSim.Services.Base; -using OpenSim.Services.Interfaces; -using OpenSim.Data; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Services.Connectors -{ - public class EstateDataService : ServiceBase, IEstateDataService - { -// private static readonly ILog m_log = -// LogManager.GetLogger( -// MethodBase.GetCurrentMethod().DeclaringType); - - protected IEstateDataStore m_database; - - public EstateDataService(IConfigSource config) - : base(config) - { - string dllName = String.Empty; - string connString = String.Empty; - - // Try reading the [DatabaseService] section, if it exists - IConfig dbConfig = config.Configs["DatabaseService"]; - if (dbConfig != null) - { - dllName = dbConfig.GetString("StorageProvider", String.Empty); - connString = dbConfig.GetString("ConnectionString", String.Empty); - connString = dbConfig.GetString("EstateConnectionString", connString); - } - - // Try reading the [EstateDataStore] section, if it exists - IConfig estConfig = config.Configs["EstateDataStore"]; - if (estConfig != null) - { - dllName = estConfig.GetString("StorageProvider", dllName); - connString = estConfig.GetString("ConnectionString", connString); - } - - // We tried, but this doesn't exist. We can't proceed - if (dllName == String.Empty) - throw new Exception("No StorageProvider configured"); - - m_database = LoadPlugin(dllName, new Object[] { connString }); - if (m_database == null) - throw new Exception("Could not find a storage interface in the given module"); - } - - public EstateSettings LoadEstateSettings(UUID regionID, bool create) - { - return m_database.LoadEstateSettings(regionID, create); - } - - public EstateSettings LoadEstateSettings(int estateID) - { - return m_database.LoadEstateSettings(estateID); - } - - public EstateSettings CreateNewEstate() - { - return m_database.CreateNewEstate(); - } - - public List LoadEstateSettingsAll() - { - return m_database.LoadEstateSettingsAll(); - } - - public void StoreEstateSettings(EstateSettings es) - { - m_database.StoreEstateSettings(es); - } - - public List GetEstates(string search) - { - return m_database.GetEstates(search); - } - - public List GetEstatesAll() - { - return m_database.GetEstatesAll(); - } - - public List GetEstatesByOwner(UUID ownerID) - { - return m_database.GetEstatesByOwner(ownerID); - } - - public bool LinkRegion(UUID regionID, int estateID) - { - return m_database.LinkRegion(regionID, estateID); - } - - public List GetRegions(int estateID) - { - return m_database.GetRegions(estateID); - } - - public bool DeleteEstate(int estateID) - { - return m_database.DeleteEstate(estateID); - } - } -} diff --git a/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs deleted file mode 100644 index 504fcaf..0000000 --- a/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs +++ /dev/null @@ -1,182 +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 OpenSimulator 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.Generic; -using OpenMetaverse; -using log4net; -using Mono.Addins; -using Nini.Config; -using System.Reflection; -using OpenSim.Services.Base; -using OpenSim.Services.Interfaces; -using OpenSim.Data; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Services.Connectors -{ - public class SimulationDataService : ServiceBase, ISimulationDataService - { -// private static readonly ILog m_log = -// LogManager.GetLogger( -// MethodBase.GetCurrentMethod().DeclaringType); - - protected ISimulationDataStore m_database; - - public SimulationDataService(IConfigSource config) - : base(config) - { - string dllName = String.Empty; - string connString = String.Empty; - - // Try reading the [DatabaseService] section, if it exists - IConfig dbConfig = config.Configs["DatabaseService"]; - if (dbConfig != null) - { - dllName = dbConfig.GetString("StorageProvider", String.Empty); - connString = dbConfig.GetString("ConnectionString", String.Empty); - } - - // Try reading the [SimulationDataStore] section - IConfig simConfig = config.Configs["SimulationDataStore"]; - if (simConfig != null) - { - dllName = simConfig.GetString("StorageProvider", dllName); - connString = simConfig.GetString("ConnectionString", connString); - } - - // We tried, but this doesn't exist. We can't proceed - if (dllName == String.Empty) - throw new Exception("No StorageProvider configured"); - - m_database = LoadPlugin(dllName, new Object[] { connString }); - if (m_database == null) - throw new Exception("Could not find a storage interface in the given module"); - } - - public void StoreObject(SceneObjectGroup obj, UUID regionUUID) - { - m_database.StoreObject(obj, regionUUID); - } - - public void RemoveObject(UUID uuid, UUID regionUUID) - { - m_database.RemoveObject(uuid, regionUUID); - } - - public void StorePrimInventory(UUID primID, ICollection items) - { - m_database.StorePrimInventory(primID, items); - } - - public List LoadObjects(UUID regionUUID) - { - return m_database.LoadObjects(regionUUID); - } - - public void StoreTerrain(double[,] terrain, UUID regionID) - { - m_database.StoreTerrain(terrain, regionID); - } - - public double[,] LoadTerrain(UUID regionID) - { - return m_database.LoadTerrain(regionID); - } - - public void StoreLandObject(ILandObject Parcel) - { - m_database.StoreLandObject(Parcel); - } - - public void RemoveLandObject(UUID globalID) - { - m_database.RemoveLandObject(globalID); - } - - public List LoadLandObjects(UUID regionUUID) - { - return m_database.LoadLandObjects(regionUUID); - } - - public void StoreRegionSettings(RegionSettings rs) - { - m_database.StoreRegionSettings(rs); - } - - public RegionSettings LoadRegionSettings(UUID regionUUID) - { - return m_database.LoadRegionSettings(regionUUID); - } - - public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) - { - return m_database.LoadRegionWindlightSettings(regionUUID); - } - - public void StoreRegionWindlightSettings(RegionLightShareData wl) - { - m_database.StoreRegionWindlightSettings(wl); - } - public void RemoveRegionWindlightSettings(UUID regionID) - { - m_database.RemoveRegionWindlightSettings(regionID); - } - - public string LoadRegionEnvironmentSettings(UUID regionUUID) - { - return m_database.LoadRegionEnvironmentSettings(regionUUID); - } - - public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) - { - m_database.StoreRegionEnvironmentSettings(regionUUID, settings); - } - - public void RemoveRegionEnvironmentSettings(UUID regionUUID) - { - m_database.RemoveRegionEnvironmentSettings(regionUUID); - } - - public void SaveExtra(UUID regionID, string name, string val) - { - m_database.SaveExtra(regionID, name, val); - } - - public void RemoveExtra(UUID regionID, string name) - { - m_database.RemoveExtra(regionID, name); - } - - public Dictionary GetExtra(UUID regionID) - { - return m_database.GetExtra(regionID); - } - } -} diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 57f2ffa..cea870b 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -79,11 +79,37 @@ namespace OpenSim.Services.Connectors.Simulation return "agent/"; } - public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) + protected virtual void PackData(OSDMap args, GridRegion source, AgentCircuitData aCircuit, GridRegion destination, uint flags) { - // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateAgent start"); - + if (source != null) + { + args["source_x"] = OSD.FromString(source.RegionLocX.ToString()); + args["source_y"] = OSD.FromString(source.RegionLocY.ToString()); + args["source_name"] = OSD.FromString(source.RegionName); + args["source_uuid"] = OSD.FromString(source.RegionID.ToString()); + if (!String.IsNullOrEmpty(source.RawServerURI)) + args["source_server_uri"] = OSD.FromString(source.RawServerURI); + } + + args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); + args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); + args["destination_name"] = OSD.FromString(destination.RegionName); + args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); + args["teleport_flags"] = OSD.FromString(flags.ToString()); + } + + public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) + { + string tmp = String.Empty; + return CreateAgent(source, destination, aCircuit, flags, out tmp, out reason); + } + + public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason) + { + m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI); reason = String.Empty; + myipaddress = String.Empty; + if (destination == null) { m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Given destination is null"); @@ -95,12 +121,7 @@ namespace OpenSim.Services.Connectors.Simulation try { OSDMap args = aCircuit.PackAgentCircuitData(); - - args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); - args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); - args["destination_name"] = OSD.FromString(destination.RegionName); - args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); - args["teleport_flags"] = OSD.FromString(flags.ToString()); + PackData(args, source, aCircuit, destination, flags); OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000); bool success = result["success"].AsBoolean(); @@ -110,11 +131,12 @@ namespace OpenSim.Services.Connectors.Simulation reason = data["reason"].AsString(); success = data["success"].AsBoolean(); + myipaddress = data["your_ip"].AsString(); return success; } // Try the old version, uncompressed - result = WebUtil.PostToService(uri, args, 30000); + result = WebUtil.PostToService(uri, args, 30000, false); if (result["Success"].AsBoolean()) { @@ -124,6 +146,7 @@ namespace OpenSim.Services.Connectors.Simulation reason = data["reason"].AsString(); success = data["success"].AsBoolean(); + myipaddress = data["your_ip"].AsString(); m_log.WarnFormat( "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); return success; @@ -228,7 +251,7 @@ namespace OpenSim.Services.Connectors.Simulation /// private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout) { - // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent start"); + // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent in {0}", destination.ServerURI); // Eventually, we want to use a caps url instead of the agentID string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; @@ -258,48 +281,10 @@ namespace OpenSim.Services.Connectors.Simulation return false; } - /// - /// Not sure what sequence causes this function to be invoked. The only calling - /// path is through the GET method - /// - public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent) - { - // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: RetrieveAgent start"); - - agent = null; - - // Eventually, we want to use a caps url instead of the agentID - string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; - - try - { - OSDMap result = WebUtil.GetFromService(uri, 10000); - if (result["Success"].AsBoolean()) - { - // OSDMap args = Util.GetOSDMap(result["_RawResult"].AsString()); - OSDMap args = (OSDMap)result["_Result"]; - if (args != null) - { - agent = new CompleteAgentData(); - agent.Unpack(args, null); - return true; - } - } - } - catch (Exception e) - { - m_log.Warn("[REMOTE SIMULATION CONNECTOR]: UpdateAgent failed with exception: " + e.ToString()); - } - - return false; - } - /// - /// - public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason) + public bool QueryAccess(GridRegion destination, UUID agentID, string agentHomeURI, bool viaTeleport, Vector3 position, List featuresAvailable, EntityTransferContext ctx, out string reason) { reason = "Failed to contact destination"; - version = "Unknown"; // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position); @@ -307,14 +292,32 @@ namespace OpenSim.Services.Connectors.Simulation if (ext == null) return false; // Eventually, we want to use a caps url instead of the agentID - string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + string uri = destination.ServerURI + AgentPath() + agentID + "/" + destination.RegionID.ToString() + "/"; OSDMap request = new OSDMap(); + request.Add("viaTeleport", OSD.FromBoolean(viaTeleport)); request.Add("position", OSD.FromString(position.ToString())); + // To those who still understad this field, we're telling them + // the lowest version just to be safe + request.Add("my_version", OSD.FromString(String.Format("SIMULATION/{0}", VersionInfo.SimulationServiceVersionSupportedMin))); + // New simulation service negotiation + request.Add("simulation_service_supported_min", OSD.FromReal(VersionInfo.SimulationServiceVersionSupportedMin)); + request.Add("simulation_service_supported_max", OSD.FromReal(VersionInfo.SimulationServiceVersionSupportedMax)); + request.Add("simulation_service_accepted_min", OSD.FromReal(VersionInfo.SimulationServiceVersionAcceptedMin)); + request.Add("simulation_service_accepted_max", OSD.FromReal(VersionInfo.SimulationServiceVersionAcceptedMax)); + + OSDArray features = new OSDArray(); + foreach (UUID feature in featuresAvailable) + features.Add(OSD.FromString(feature.ToString())); + + request.Add("features", features); + + if (agentHomeURI != null) + request.Add("agent_home_uri", OSD.FromString(agentHomeURI)); try { - OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 30000, false); + OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 30000, false, false); bool success = result["success"].AsBoolean(); if (result.ContainsKey("_Result")) { @@ -325,15 +328,32 @@ namespace OpenSim.Services.Connectors.Simulation success = data["success"]; reason = data["reason"].AsString(); - if (data["version"] != null && data["version"].AsString() != string.Empty) - version = data["version"].AsString(); + // We will need to plumb this and start sing the outbound version as well + // TODO: lay the pipe for version plumbing + if (data.ContainsKey("negotiated_inbound_version") && data["negotiated_inbound_version"] != null) + { + ctx.InboundVersion = (float)data["negotiated_inbound_version"].AsReal(); + ctx.OutboundVersion = (float)data["negotiated_outbound_version"].AsReal(); + } + else if (data["version"] != null && data["version"].AsString() != string.Empty) + { + string versionString = data["version"].AsString(); + String[] parts = versionString.Split(new char[] {'/'}); + if (parts.Length > 1) + { + ctx.InboundVersion = float.Parse(parts[1]); + ctx.OutboundVersion = float.Parse(parts[1]); + } + } + if (data.ContainsKey("variable_wearables_count_supported")) + ctx.VariableWearablesSupported = true; m_log.DebugFormat( - "[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1}, reason {2}, version {3} ({4})", - uri, success, reason, version, data["version"].AsString()); + "[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1}, reason {2}, version {3}/{4}", + uri, success, reason, ctx.InboundVersion, ctx.OutboundVersion); } - if (!success) + if (!success || ctx.InboundVersion == 0f || ctx.OutboundVersion == 0f) { // If we don't check this then OpenSimulator 0.7.3.1 and some period before will never see the // actual failure message @@ -359,6 +379,17 @@ namespace OpenSim.Services.Connectors.Simulation return false; } + + featuresAvailable.Clear(); + + if (result.ContainsKey("features")) + { + OSDArray array = (OSDArray)result["features"]; + + foreach (OSD o in array) + featuresAvailable.Add(new UUID(o.AsString())); + } + return success; } catch (Exception e) @@ -377,7 +408,7 @@ namespace OpenSim.Services.Connectors.Simulation try { - WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false); + WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false, false); } catch (Exception e) { @@ -389,15 +420,14 @@ namespace OpenSim.Services.Connectors.Simulation /// /// - public bool CloseAgent(GridRegion destination, UUID id) + public bool CloseAgent(GridRegion destination, UUID id, string auth_code) { -// m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CloseAgent start"); - - string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/?auth=" + auth_code; + m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CloseAgent {0}", uri); try { - WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false); + WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false, false); } catch (Exception e) { @@ -444,11 +474,18 @@ namespace OpenSim.Services.Connectors.Simulation args["destination_name"] = OSD.FromString(destination.RegionName); args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); - WebUtil.PostToService(uri, args, 40000); + OSDMap result = WebUtil.PostToService(uri, args, 40000, false); + + if (result == null) + return false; + bool success = result["success"].AsBoolean(); + if (!success) + return false; } catch (Exception e) { m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR] CreateObject failed with exception; {0}",e.ToString()); + return false; } return true; diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs index 6d5ce28..c21db54 100644 --- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs +++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs @@ -32,14 +32,15 @@ using System.IO; using System.Reflection; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Communications; + +using OpenSim.Framework.ServiceAuth; using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenMetaverse; namespace OpenSim.Services.Connectors { - public class UserAccountServicesConnector : IUserAccountService + public class UserAccountServicesConnector : BaseServiceConnector, IUserAccountService { private static readonly ILog m_log = LogManager.GetLogger( @@ -79,6 +80,8 @@ namespace OpenSim.Services.Connectors throw new Exception("User account connector init error"); } m_ServerURI = serviceURI; + + base.Initialise(source, "UserAccountService"); } public virtual UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) @@ -144,7 +147,8 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply == null || (reply != null && reply == string.Empty)) { m_log.DebugFormat("[ACCOUNT CONNECTOR]: GetUserAccounts received null or empty reply"); @@ -162,7 +166,7 @@ namespace OpenSim.Services.Connectors if (replyData != null) { - if (replyData.ContainsKey("result") && replyData.ContainsKey("result").ToString() == "null") + if (replyData.ContainsKey("result") && replyData["result"].ToString() == "null") { return accounts; } @@ -187,6 +191,10 @@ namespace OpenSim.Services.Connectors return accounts; } + public void InvalidateCache(UUID userID) + { + } + public virtual bool StoreUserAccount(UserAccount data) { Dictionary sendData = new Dictionary(); @@ -207,9 +215,39 @@ namespace OpenSim.Services.Connectors sendData[kvp.Key] = kvp.Value.ToString(); } - return SendAndGetBoolReply(sendData); + if (SendAndGetReply(sendData) != null) + return true; + else + return false; } + /// + /// Create user remotely. Note this this is not part of the IUserAccountsService + /// + /// + /// + /// + /// + /// + /// + public virtual UserAccount CreateUser(string first, string last, string password, string email, UUID scopeID) + { + Dictionary sendData = new Dictionary(); + //sendData["SCOPEID"] = scopeID.ToString(); + sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); + sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); + sendData["METHOD"] = "createuser"; + + sendData["FirstName"] = first; + sendData["LastName"] = last; + sendData["Password"] = password; + if (!string.IsNullOrEmpty(email)) + sendData["Email"] = first; + sendData["ScopeID"] = scopeID.ToString(); + + return SendAndGetReply(sendData); + } + private UserAccount SendAndGetReply(Dictionary sendData) { string reply = string.Empty; @@ -220,7 +258,8 @@ namespace OpenSim.Services.Connectors { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply == null || (reply != null && reply == string.Empty)) { m_log.DebugFormat("[ACCOUNT CONNECTOR]: GetUserAccount received null or empty reply"); @@ -251,14 +290,16 @@ namespace OpenSim.Services.Connectors { string reqString = ServerUtils.BuildQueryString(sendData); string uri = m_ServerURI + "/accounts"; - // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString); + //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString); try { string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, - reqString); + reqString, + m_Auth); if (reply != string.Empty) { + //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: reply = {0}", reply); Dictionary replyData = ServerUtils.ParseXmlResponse(reply); if (replyData.ContainsKey("result")) diff --git a/OpenSim/Services/EstateService/EstateDataService.cs b/OpenSim/Services/EstateService/EstateDataService.cs new file mode 100644 index 0000000..f6a8654 --- /dev/null +++ b/OpenSim/Services/EstateService/EstateDataService.cs @@ -0,0 +1,136 @@ +/* + * 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 OpenSimulator 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.Generic; +using OpenMetaverse; +using log4net; +using Nini.Config; +using System.Reflection; +using OpenSim.Services.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Data; +using OpenSim.Framework; + +namespace OpenSim.Services.EstateService +{ + public class EstateDataService : ServiceBase, IEstateDataService + { +// private static readonly ILog m_log = +// LogManager.GetLogger( +// MethodBase.GetCurrentMethod().DeclaringType); + + protected IEstateDataStore m_database; + + public EstateDataService(IConfigSource config) + : base(config) + { + string dllName = String.Empty; + string connString = String.Empty; + + // Try reading the [DatabaseService] section, if it exists + IConfig dbConfig = config.Configs["DatabaseService"]; + if (dbConfig != null) + { + dllName = dbConfig.GetString("StorageProvider", String.Empty); + connString = dbConfig.GetString("ConnectionString", String.Empty); + connString = dbConfig.GetString("EstateConnectionString", connString); + } + + // Try reading the [EstateDataStore] section, if it exists + IConfig estConfig = config.Configs["EstateDataStore"]; + if (estConfig != null) + { + dllName = estConfig.GetString("StorageProvider", dllName); + connString = estConfig.GetString("ConnectionString", connString); + } + + // We tried, but this doesn't exist. We can't proceed + if (dllName == String.Empty) + throw new Exception("No StorageProvider configured"); + + m_database = LoadPlugin(dllName, new Object[] { connString }); + if (m_database == null) + throw new Exception("Could not find a storage interface in the given module"); + } + + public EstateSettings LoadEstateSettings(UUID regionID, bool create) + { + return m_database.LoadEstateSettings(regionID, create); + } + + public EstateSettings LoadEstateSettings(int estateID) + { + return m_database.LoadEstateSettings(estateID); + } + + public EstateSettings CreateNewEstate() + { + return m_database.CreateNewEstate(); + } + + public List LoadEstateSettingsAll() + { + return m_database.LoadEstateSettingsAll(); + } + + public void StoreEstateSettings(EstateSettings es) + { + m_database.StoreEstateSettings(es); + } + + public List GetEstates(string search) + { + return m_database.GetEstates(search); + } + + public List GetEstatesAll() + { + return m_database.GetEstatesAll(); + } + + public List GetEstatesByOwner(UUID ownerID) + { + return m_database.GetEstatesByOwner(ownerID); + } + + public bool LinkRegion(UUID regionID, int estateID) + { + return m_database.LinkRegion(regionID, estateID); + } + + public List GetRegions(int estateID) + { + return m_database.GetRegions(estateID); + } + + public bool DeleteEstate(int estateID) + { + return m_database.DeleteEstate(estateID); + } + } +} diff --git a/OpenSim/Services/FSAssetService/FSAssetService.cs b/OpenSim/Services/FSAssetService/FSAssetService.cs new file mode 100644 index 0000000..1bab687 --- /dev/null +++ b/OpenSim/Services/FSAssetService/FSAssetService.cs @@ -0,0 +1,723 @@ +/* + * 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 OpenSimulator 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.Diagnostics; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Text; +using System.Threading; +using System.Reflection; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Framework.Serialization.External; +using OpenSim.Framework.Console; +using OpenSim.Server.Base; +using OpenSim.Services.Base; +using OpenSim.Services.Interfaces; +using Nini.Config; +using log4net; +using OpenMetaverse; +using System.Security.Cryptography; + +namespace OpenSim.Services.FSAssetService +{ + public class FSAssetConnector : ServiceBase, IAssetService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + static System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + static SHA256CryptoServiceProvider SHA256 = new SHA256CryptoServiceProvider(); + + static byte[] ToCString(string s) + { + byte[] ret = enc.GetBytes(s); + Array.Resize(ref ret, ret.Length + 1); + ret[ret.Length - 1] = 0; + + return ret; + } + + protected IAssetLoader m_AssetLoader = null; + protected IFSAssetDataPlugin m_DataConnector = null; + protected IAssetService m_FallbackService; + protected Thread m_WriterThread; + protected Thread m_StatsThread; + protected string m_SpoolDirectory; + protected object m_readLock = new object(); + protected object m_statsLock = new object(); + protected int m_readCount = 0; + protected int m_readTicks = 0; + protected int m_missingAssets = 0; + protected int m_missingAssetsFS = 0; + protected string m_FSBase; + + private static bool m_Initialized; + private bool m_MainInstance; + + public FSAssetConnector(IConfigSource config) + : this(config, "AssetService") + { + } + + public FSAssetConnector(IConfigSource config, string configName) : base(config) + { + if (!m_Initialized) + { + m_Initialized = true; + m_MainInstance = true; + + MainConsole.Instance.Commands.AddCommand("fs", false, + "show assets", "show assets", "Show asset stats", + HandleShowAssets); + MainConsole.Instance.Commands.AddCommand("fs", false, + "show digest", "show digest ", "Show asset digest", + HandleShowDigest); + MainConsole.Instance.Commands.AddCommand("fs", false, + "delete asset", "delete asset ", + "Delete asset from database", + HandleDeleteAsset); + MainConsole.Instance.Commands.AddCommand("fs", false, + "import", "import [ ]", + "Import legacy assets", + HandleImportAssets); + MainConsole.Instance.Commands.AddCommand("fs", false, + "force import", "force import
[ ]", + "Import legacy assets, overwriting current content", + HandleImportAssets); + } + + IConfig assetConfig = config.Configs[configName]; + + if (assetConfig == null) + throw new Exception("No AssetService configuration"); + + // Get Database Connector from Asset Config (If present) + string dllName = assetConfig.GetString("StorageProvider", string.Empty); + string m_ConnectionString = assetConfig.GetString("ConnectionString", string.Empty); + string m_Realm = assetConfig.GetString("Realm", "fsassets"); + + int SkipAccessTimeDays = assetConfig.GetInt("DaysBetweenAccessTimeUpdates", 0); + + // If not found above, fallback to Database defaults + IConfig dbConfig = config.Configs["DatabaseService"]; + + if (dbConfig != null) + { + if (dllName == String.Empty) + dllName = dbConfig.GetString("StorageProvider", String.Empty); + + if (m_ConnectionString == String.Empty) + m_ConnectionString = dbConfig.GetString("ConnectionString", String.Empty); + } + + // No databse connection found in either config + if (dllName.Equals(String.Empty)) + throw new Exception("No StorageProvider configured"); + + if (m_ConnectionString.Equals(String.Empty)) + throw new Exception("Missing database connection string"); + + // Create Storage Provider + m_DataConnector = LoadPlugin(dllName); + + if (m_DataConnector == null) + throw new Exception(string.Format("Could not find a storage interface in the module {0}", dllName)); + + // Initialize DB And perform any migrations required + m_DataConnector.Initialise(m_ConnectionString, m_Realm, SkipAccessTimeDays); + + // Setup Fallback Service + string str = assetConfig.GetString("FallbackService", string.Empty); + + if (str != string.Empty) + { + object[] args = new object[] { config }; + m_FallbackService = LoadPlugin(str, args); + if (m_FallbackService != null) + { + m_log.Info("[FSASSETS]: Fallback service loaded"); + } + else + { + m_log.Error("[FSASSETS]: Failed to load fallback service"); + } + } + + // Setup directory structure including temp directory + m_SpoolDirectory = assetConfig.GetString("SpoolDirectory", "/tmp"); + + string spoolTmp = Path.Combine(m_SpoolDirectory, "spool"); + + Directory.CreateDirectory(spoolTmp); + + m_FSBase = assetConfig.GetString("BaseDirectory", String.Empty); + if (m_FSBase == String.Empty) + { + m_log.ErrorFormat("[FSASSETS]: BaseDirectory not specified"); + throw new Exception("Configuration error"); + } + + if (m_MainInstance) + { + string loader = assetConfig.GetString("DefaultAssetLoader", string.Empty); + if (loader != string.Empty) + { + m_AssetLoader = LoadPlugin(loader); + string loaderArgs = assetConfig.GetString("AssetLoaderArgs", string.Empty); + m_log.InfoFormat("[FSASSETS]: Loading default asset set from {0}", loaderArgs); + m_AssetLoader.ForEachDefaultXmlAsset(loaderArgs, + delegate(AssetBase a) + { + Store(a, false); + }); + } + + m_WriterThread = new Thread(Writer); + m_WriterThread.Start(); + m_StatsThread = new Thread(Stats); + m_StatsThread.Start(); + } + + m_log.Info("[FSASSETS]: FS asset service enabled"); + } + + private void Stats() + { + while (true) + { + Thread.Sleep(60000); + + lock (m_statsLock) + { + if (m_readCount > 0) + { + double avg = (double)m_readTicks / (double)m_readCount; +// if (avg > 10000) +// Environment.Exit(0); + m_log.InfoFormat("[FSASSETS]: Read stats: {0} files, {1} ticks, avg {2:F2}, missing {3}, FS {4}", m_readCount, m_readTicks, (double)m_readTicks / (double)m_readCount, m_missingAssets, m_missingAssetsFS); + } + m_readCount = 0; + m_readTicks = 0; + m_missingAssets = 0; + m_missingAssetsFS = 0; + } + } + } + + private void Writer() + { + m_log.Info("[FSASSETS]: Writer started"); + + while (true) + { + string[] files = Directory.GetFiles(m_SpoolDirectory); + + if (files.Length > 0) + { + int tickCount = Environment.TickCount; + for (int i = 0 ; i < files.Length ; i++) + { + string hash = Path.GetFileNameWithoutExtension(files[i]); + string s = HashToFile(hash); + string diskFile = Path.Combine(m_FSBase, s); + + Directory.CreateDirectory(Path.GetDirectoryName(diskFile)); + try + { + byte[] data = File.ReadAllBytes(files[i]); + + using (GZipStream gz = new GZipStream(new FileStream(diskFile + ".gz", FileMode.Create), CompressionMode.Compress)) + { + gz.Write(data, 0, data.Length); + gz.Close(); + } + File.Delete(files[i]); + + //File.Move(files[i], diskFile); + } + catch(System.IO.IOException e) + { + if (e.Message.StartsWith("Win32 IO returned ERROR_ALREADY_EXISTS")) + File.Delete(files[i]); + else + throw; + } + } + int totalTicks = System.Environment.TickCount - tickCount; + if (totalTicks > 0) // Wrap? + { + m_log.InfoFormat("[FSASSETS]: Write cycle complete, {0} files, {1} ticks, avg {2:F2}", files.Length, totalTicks, (double)totalTicks / (double)files.Length); + } + } + + Thread.Sleep(1000); + } + } + + string GetSHA256Hash(byte[] data) + { + byte[] hash = SHA256.ComputeHash(data); + + return BitConverter.ToString(hash).Replace("-", String.Empty); + } + + public string HashToPath(string hash) + { + if (hash == null || hash.Length < 10) + return "junkyard"; + + return Path.Combine(hash.Substring(0, 3), + Path.Combine(hash.Substring(3, 3))); + /* + * The below is what core would normally use. + * This is modified to work in OSGrid, as seen + * above, because the SRAS data is structured + * that way. + */ + /* + return Path.Combine(hash.Substring(0, 2), + Path.Combine(hash.Substring(2, 2), + Path.Combine(hash.Substring(4, 2), + hash.Substring(6, 4)))); + */ + } + + private bool AssetExists(string hash) + { + string s = HashToFile(hash); + string diskFile = Path.Combine(m_FSBase, s); + + if (File.Exists(diskFile + ".gz") || File.Exists(diskFile)) + return true; + + return false; + } + + public virtual bool[] AssetsExist(string[] ids) + { + UUID[] uuid = Array.ConvertAll(ids, id => UUID.Parse(id)); + return m_DataConnector.AssetsExist(uuid); + } + + public string HashToFile(string hash) + { + return Path.Combine(HashToPath(hash), hash); + } + + public virtual AssetBase Get(string id) + { + string hash; + + return Get(id, out hash); + } + + private AssetBase Get(string id, out string sha) + { + string hash = string.Empty; + + int startTime = System.Environment.TickCount; + AssetMetadata metadata; + + lock (m_readLock) + { + metadata = m_DataConnector.Get(id, out hash); + } + + sha = hash; + + if (metadata == null) + { + AssetBase asset = null; + if (m_FallbackService != null) + { + asset = m_FallbackService.Get(id); + if (asset != null) + { + asset.Metadata.ContentType = + SLUtil.SLAssetTypeToContentType((int)asset.Type); + sha = GetSHA256Hash(asset.Data); + m_log.InfoFormat("[FSASSETS]: Added asset {0} from fallback to local store", id); + Store(asset); + } + } + if (asset == null) + { + // m_log.InfoFormat("[FSASSETS]: Asset {0} not found", id); + m_missingAssets++; + } + return asset; + } + AssetBase newAsset = new AssetBase(); + newAsset.Metadata = metadata; + try + { + newAsset.Data = GetFsData(hash); + if (newAsset.Data.Length == 0) + { + AssetBase asset = null; + if (m_FallbackService != null) + { + asset = m_FallbackService.Get(id); + if (asset != null) + { + asset.Metadata.ContentType = + SLUtil.SLAssetTypeToContentType((int)asset.Type); + sha = GetSHA256Hash(asset.Data); + m_log.InfoFormat("[FSASSETS]: Added asset {0} from fallback to local store", id); + Store(asset); + } + } + if (asset == null) + m_missingAssetsFS++; + // m_log.InfoFormat("[FSASSETS]: Asset {0}, hash {1} not found in FS", id, hash); + else + { + // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) + // Fix bad assets before sending them elsewhere + if (asset.Type == (int)AssetType.Object && asset.Data != null) + { + string xml = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(asset.Data)); + asset.Data = Utils.StringToBytes(xml); + } + return asset; + } + } + + lock (m_statsLock) + { + m_readTicks += Environment.TickCount - startTime; + m_readCount++; + } + + // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) + // Fix bad assets before sending them elsewhere + if (newAsset.Type == (int)AssetType.Object && newAsset.Data != null) + { + string xml = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(newAsset.Data)); + newAsset.Data = Utils.StringToBytes(xml); + } + + return newAsset; + } + catch (Exception exception) + { + m_log.Error(exception.ToString()); + Thread.Sleep(5000); + Environment.Exit(1); + return null; + } + } + + public virtual AssetMetadata GetMetadata(string id) + { + string hash; + return m_DataConnector.Get(id, out hash); + } + + public virtual byte[] GetData(string id) + { + string hash; + if (m_DataConnector.Get(id, out hash) == null) + return null; + + return GetFsData(hash); + } + + public bool Get(string id, Object sender, AssetRetrieved handler) + { + AssetBase asset = Get(id); + + handler(id, sender, asset); + + return true; + } + + public byte[] GetFsData(string hash) + { + string spoolFile = Path.Combine(m_SpoolDirectory, hash + ".asset"); + + if (File.Exists(spoolFile)) + { + try + { + byte[] content = File.ReadAllBytes(spoolFile); + + return content; + } + catch + { + } + } + + string file = HashToFile(hash); + string diskFile = Path.Combine(m_FSBase, file); + + if (File.Exists(diskFile + ".gz")) + { + try + { + using (GZipStream gz = new GZipStream(new FileStream(diskFile + ".gz", FileMode.Open, FileAccess.Read), CompressionMode.Decompress)) + { + using (MemoryStream ms = new MemoryStream()) + { + byte[] data = new byte[32768]; + int bytesRead; + + do + { + bytesRead = gz.Read(data, 0, 32768); + if (bytesRead > 0) + ms.Write(data, 0, bytesRead); + } while (bytesRead > 0); + + return ms.ToArray(); + } + } + } + catch (Exception) + { + return new Byte[0]; + } + } + else if (File.Exists(diskFile)) + { + try + { + byte[] content = File.ReadAllBytes(diskFile); + + return content; + } + catch + { + } + } + return new Byte[0]; + + } + + public virtual string Store(AssetBase asset) + { + return Store(asset, false); + } + + private string Store(AssetBase asset, bool force) + { + int tickCount = Environment.TickCount; + string hash = GetSHA256Hash(asset.Data); + + if (!AssetExists(hash)) + { + string tempFile = Path.Combine(Path.Combine(m_SpoolDirectory, "spool"), hash + ".asset"); + string finalFile = Path.Combine(m_SpoolDirectory, hash + ".asset"); + + if (!File.Exists(finalFile)) + { + // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) + // Fix bad assets before storing on this server + if (asset.Type == (int)AssetType.Object && asset.Data != null) + { + string xml = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(asset.Data)); + asset.Data = Utils.StringToBytes(xml); + } + + FileStream fs = File.Create(tempFile); + + fs.Write(asset.Data, 0, asset.Data.Length); + + fs.Close(); + + File.Move(tempFile, finalFile); + } + } + + if (asset.ID == string.Empty) + { + if (asset.FullID == UUID.Zero) + { + asset.FullID = UUID.Random(); + } + asset.ID = asset.FullID.ToString(); + } + else if (asset.FullID == UUID.Zero) + { + UUID uuid = UUID.Zero; + if (UUID.TryParse(asset.ID, out uuid)) + { + asset.FullID = uuid; + } + else + { + asset.FullID = UUID.Random(); + } + } + + if (!m_DataConnector.Store(asset.Metadata, hash)) + { + return UUID.Zero.ToString(); + } + else + { + return asset.ID; + } + } + + public bool UpdateContent(string id, byte[] data) + { + return false; + +// string oldhash; +// AssetMetadata meta = m_DataConnector.Get(id, out oldhash); +// +// if (meta == null) +// return false; +// +// AssetBase asset = new AssetBase(); +// asset.Metadata = meta; +// asset.Data = data; +// +// Store(asset); +// +// return true; + } + + public virtual bool Delete(string id) + { + m_DataConnector.Delete(id); + + return true; + } + + private void HandleShowAssets(string module, string[] args) + { + int num = m_DataConnector.Count(); + MainConsole.Instance.Output(string.Format("Total asset count: {0}", num)); + } + + private void HandleShowDigest(string module, string[] args) + { + if (args.Length < 3) + { + MainConsole.Instance.Output("Syntax: show digest "); + return; + } + + string hash; + AssetBase asset = Get(args[2], out hash); + + if (asset == null || asset.Data.Length == 0) + { + MainConsole.Instance.Output("Asset not found"); + return; + } + + int i; + + MainConsole.Instance.Output(String.Format("Name: {0}", asset.Name)); + MainConsole.Instance.Output(String.Format("Description: {0}", asset.Description)); + MainConsole.Instance.Output(String.Format("Type: {0}", asset.Type)); + MainConsole.Instance.Output(String.Format("Content-type: {0}", asset.Metadata.ContentType)); + MainConsole.Instance.Output(String.Format("Flags: {0}", asset.Metadata.Flags.ToString())); + MainConsole.Instance.Output(String.Format("FS file: {0}", HashToFile(hash))); + + for (i = 0 ; i < 5 ; i++) + { + int off = i * 16; + if (asset.Data.Length <= off) + break; + int len = 16; + if (asset.Data.Length < off + len) + len = asset.Data.Length - off; + + byte[] line = new byte[len]; + Array.Copy(asset.Data, off, line, 0, len); + + string text = BitConverter.ToString(line); + MainConsole.Instance.Output(String.Format("{0:x4}: {1}", off, text)); + } + } + + private void HandleDeleteAsset(string module, string[] args) + { + if (args.Length < 3) + { + MainConsole.Instance.Output("Syntax: delete asset "); + return; + } + + AssetBase asset = Get(args[2]); + + if (asset == null || asset.Data.Length == 0) + { + MainConsole.Instance.Output("Asset not found"); + return; + } + + m_DataConnector.Delete(args[2]); + + MainConsole.Instance.Output("Asset deleted"); + } + + private void HandleImportAssets(string module, string[] args) + { + bool force = false; + if (args[0] == "force") + { + force = true; + List list = new List(args); + list.RemoveAt(0); + args = list.ToArray(); + } + if (args.Length < 3) + { + MainConsole.Instance.Output("Syntax: import
[ ]"); + } + else + { + string conn = args[1]; + string table = args[2]; + int start = 0; + int count = -1; + if (args.Length > 3) + { + start = Convert.ToInt32(args[3]); + } + if (args.Length > 4) + { + count = Convert.ToInt32(args[4]); + } + m_DataConnector.Import(conn, table, start, count, force, new FSStoreDelegate(Store)); + } + } + + public AssetBase GetCached(string id) + { + return Get(id); + } + } +} diff --git a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs index 58c7283..1e3560b 100644 --- a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs index dddb091..87fb6a9 100644 --- a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index ee3b858..0c502a2 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -46,6 +46,7 @@ namespace OpenSim.Services.GridService private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); + private string LogHeader = "[GRID SERVICE]"; private bool m_DeleteOnUnregister = true; private static GridService m_RootInstance = null; @@ -56,6 +57,10 @@ namespace OpenSim.Services.GridService protected bool m_AllowDuplicateNames = false; protected bool m_AllowHypergridMapSearch = false; + protected bool m_SuppressVarregionOverlapCheckOnRegistration = false; + + private static Dictionary m_ExtraFeatures = new Dictionary(); + public GridService(IConfigSource config) : base(config) { @@ -63,6 +68,9 @@ namespace OpenSim.Services.GridService m_config = config; IConfig gridConfig = config.Configs["GridService"]; + + bool suppressConsoleCommands = false; + if (gridConfig != null) { m_DeleteOnUnregister = gridConfig.GetBoolean("DeleteOnUnregister", true); @@ -76,32 +84,33 @@ namespace OpenSim.Services.GridService } m_AllowDuplicateNames = gridConfig.GetBoolean("AllowDuplicateNames", m_AllowDuplicateNames); m_AllowHypergridMapSearch = gridConfig.GetBoolean("AllowHypergridMapSearch", m_AllowHypergridMapSearch); + + m_SuppressVarregionOverlapCheckOnRegistration = gridConfig.GetBoolean("SuppressVarregionOverlapCheckOnRegistration", m_SuppressVarregionOverlapCheckOnRegistration); + + // This service is also used locally by a simulator running in grid mode. This switches prevents + // inappropriate console commands from being registered + suppressConsoleCommands = gridConfig.GetBoolean("SuppressConsoleCommands", suppressConsoleCommands); } - + if (m_RootInstance == null) { m_RootInstance = this; - if (MainConsole.Instance != null) + if (!suppressConsoleCommands && MainConsole.Instance != null) { MainConsole.Instance.Commands.AddCommand("Regions", true, "deregister region id", - "deregister region id ", + "deregister region id +", "Deregister a region manually.", String.Empty, HandleDeregisterRegion); - // A messy way of stopping this command being added if we are in standalone (since the simulator - // has an identically named command - // - // XXX: We're relying on the OpenSimulator version being registered first, which is not well defined. - if (MainConsole.Instance.Commands.Resolve(new string[] { "show", "regions" }).Length == 0) - MainConsole.Instance.Commands.AddCommand("Regions", true, - "show regions", - "show regions", - "Show details on all regions", - String.Empty, - HandleShowRegions); + MainConsole.Instance.Commands.AddCommand("Regions", true, + "show regions", + "show regions", + "Show details on all regions", + String.Empty, + HandleShowRegions); MainConsole.Instance.Commands.AddCommand("Regions", true, "show region name", @@ -117,17 +126,72 @@ namespace OpenSim.Services.GridService "For example, show region at 1000 1000", HandleShowRegionAt); - MainConsole.Instance.Commands.AddCommand("Regions", true, - "set region flags", - "set region flags ", - "Set database flags for region", + MainConsole.Instance.Commands.AddCommand("General", true, + "show grid size", + "show grid size", + "Show the current grid size (excluding hyperlink references)", String.Empty, - HandleSetFlags); + HandleShowGridSize); + + MainConsole.Instance.Commands.AddCommand("Regions", true, + "set region flags", + "set region flags ", + "Set database flags for region", + String.Empty, + HandleSetFlags); } + + if (!suppressConsoleCommands) + SetExtraServiceURLs(config); + m_HypergridLinker = new HypergridLinker(m_config, this, m_Database); } } + private void SetExtraServiceURLs(IConfigSource config) + { + IConfig loginConfig = config.Configs["LoginService"]; + IConfig gridConfig = config.Configs["GridService"]; + + if (loginConfig == null || gridConfig == null) + return; + + string configVal; + + configVal = loginConfig.GetString("SearchURL", string.Empty); + if (!string.IsNullOrEmpty(configVal)) + m_ExtraFeatures["search-server-url"] = configVal; + + configVal = loginConfig.GetString("MapTileURL", string.Empty); + if (!string.IsNullOrEmpty(configVal)) + { + // This URL must end with '/', the viewer doesn't check + configVal = configVal.Trim(); + if (!configVal.EndsWith("/")) + configVal = configVal + "/"; + m_ExtraFeatures["map-server-url"] = configVal; + } + + configVal = loginConfig.GetString("DestinationGuide", string.Empty); + if (!string.IsNullOrEmpty(configVal)) + m_ExtraFeatures["destination-guide-url"] = configVal; + + configVal = Util.GetConfigVarFromSections( + config, "GatekeeperURI", new string[] { "Startup", "Hypergrid" }, String.Empty); + if (!string.IsNullOrEmpty(configVal)) + m_ExtraFeatures["GridURL"] = configVal; + + configVal = Util.GetConfigVarFromSections( + config, "GridName", new string[] { "Const", "Hypergrid" }, String.Empty); + if (string.IsNullOrEmpty(configVal)) + configVal = Util.GetConfigVarFromSections( + config, "gridname", new string[] { "GridInfo" }, String.Empty); + if (!string.IsNullOrEmpty(configVal)) + m_ExtraFeatures["GridName"] = configVal; + + m_ExtraFeatures["ExportSupported"] = gridConfig.GetString("ExportSupported", "true"); + } + #region IGridService public string RegisterRegion(UUID scopeID, GridRegion regionInfos) @@ -137,12 +201,19 @@ namespace OpenSim.Services.GridService if (regionInfos.RegionID == UUID.Zero) return "Invalid RegionID - cannot be zero UUID"; - RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); - if ((region != null) && (region.RegionID != regionInfos.RegionID)) + String reason = "Region overlaps another region"; + RegionData region = FindAnyConflictingRegion(regionInfos, scopeID, out reason); + // If there is a conflicting region, if it has the same ID and same coordinates + // then it is a region re-registering (permissions and ownership checked later). + if ((region != null) + && ( (region.coordX != regionInfos.RegionCoordX) + || (region.coordY != regionInfos.RegionCoordY) + || (region.RegionID != regionInfos.RegionID) ) + ) { - m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.", - regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); - return "Region overlaps another region"; + // If not same ID and same coordinates, this new region has conflicts and can't be registered. + m_log.WarnFormat("{0} Register region conflict in scope {1}. {2}", LogHeader, scopeID, reason); + return reason; } if (region != null) @@ -185,15 +256,15 @@ namespace OpenSim.Services.GridService if (!m_AllowDuplicateNames) { - List dupe = m_Database.Get(regionInfos.RegionName, scopeID); + List dupe = m_Database.Get(Util.EscapeForLike(regionInfos.RegionName), scopeID); if (dupe != null && dupe.Count > 0) { foreach (RegionData d in dupe) { if (d.RegionID != regionInfos.RegionID) { - m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register duplicate name with ID {1}.", - regionInfos.RegionName, regionInfos.RegionID); + m_log.WarnFormat("[GRID SERVICE]: Region tried to register using a duplicate name. New region: {0} ({1}), existing region: {2} ({3}).", + regionInfos.RegionName, regionInfos.RegionID, d.RegionName, d.RegionID); return "Duplicate region name"; } } @@ -265,12 +336,121 @@ namespace OpenSim.Services.GridService m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e); } - m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3}", - regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionCoordX, regionInfos.RegionCoordY); + m_log.InfoFormat + ("[GRID SERVICE]: Region {0} ({1}, {2}x{3}) registered at {4},{5} with flags {6}", + regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionSizeX, regionInfos.RegionSizeY, + regionInfos.RegionCoordX, regionInfos.RegionCoordY, + (OpenSim.Framework.RegionFlags)flags); return String.Empty; } + /// + /// Search the region map for regions conflicting with this region. + /// The region to be added is passed and we look for any existing regions that are + /// in the requested location, that are large varregions that overlap this region, or + /// are previously defined regions that would lie under this new region. + /// + /// Information on region requested to be added to the world map + /// Grid id for region + /// The reason the returned region conflicts with passed region + /// + private RegionData FindAnyConflictingRegion(GridRegion regionInfos, UUID scopeID, out string reason) + { + reason = "Reregistration"; + // First see if there is an existing region right where this region is trying to go + // (We keep this result so it can be returned if suppressing errors) + RegionData noErrorRegion = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); + RegionData region = noErrorRegion; + if (region != null + && region.RegionID == regionInfos.RegionID + && region.sizeX == regionInfos.RegionSizeX + && region.sizeY == regionInfos.RegionSizeY) + { + // If this seems to be exactly the same region, return this as it could be + // a re-registration (permissions checked by calling routine). + m_log.DebugFormat("{0} FindAnyConflictingRegion: re-register of {1}", + LogHeader, RegionString(regionInfos)); + return region; + } + + // No region exactly there or we're resizing an existing region. + // Fetch regions that could be varregions overlapping requested location. + int xmin = regionInfos.RegionLocX - (int)Constants.MaximumRegionSize + 10; + int xmax = regionInfos.RegionLocX; + int ymin = regionInfos.RegionLocY - (int)Constants.MaximumRegionSize + 10; + int ymax = regionInfos.RegionLocY; + List rdatas = m_Database.Get(xmin, ymin, xmax, ymax, scopeID); + foreach (RegionData rdata in rdatas) + { + // m_log.DebugFormat("{0} FindAnyConflictingRegion: find existing. Checking {1}", LogHeader, RegionString(rdata) ); + if ( (rdata.posX + rdata.sizeX > regionInfos.RegionLocX) + && (rdata.posY + rdata.sizeY > regionInfos.RegionLocY) ) + { + region = rdata; + m_log.WarnFormat("{0} FindAnyConflictingRegion: conflict of {1} by existing varregion {2}", + LogHeader, RegionString(regionInfos), RegionString(region)); + reason = String.Format("Region location is overlapped by existing varregion {0}", + RegionString(region)); + + if (m_SuppressVarregionOverlapCheckOnRegistration) + region = noErrorRegion; + return region; + } + } + + // There isn't a region that overlaps this potential region. + // See if this potential region overlaps an existing region. + // First, a shortcut of not looking for overlap if new region is legacy region sized + // and connot overlap anything. + if (regionInfos.RegionSizeX != Constants.RegionSize + || regionInfos.RegionSizeY != Constants.RegionSize) + { + // trim range looked for so we don't pick up neighbor regions just off the edges + xmin = regionInfos.RegionLocX; + xmax = regionInfos.RegionLocX + regionInfos.RegionSizeX - 10; + ymin = regionInfos.RegionLocY; + ymax = regionInfos.RegionLocY + regionInfos.RegionSizeY - 10; + rdatas = m_Database.Get(xmin, ymin, xmax, ymax, scopeID); + + // If the region is being resized, the found region could be ourself. + foreach (RegionData rdata in rdatas) + { + // m_log.DebugFormat("{0} FindAnyConflictingRegion: see if overlap. Checking {1}", LogHeader, RegionString(rdata) ); + if (region == null || region.RegionID != regionInfos.RegionID) + { + region = rdata; + m_log.WarnFormat("{0} FindAnyConflictingRegion: conflict of varregion {1} overlaps existing region {2}", + LogHeader, RegionString(regionInfos), RegionString(region)); + reason = String.Format("Region {0} would overlap existing region {1}", + RegionString(regionInfos), RegionString(region)); + + if (m_SuppressVarregionOverlapCheckOnRegistration) + region = noErrorRegion; + return region; + } + } + } + + // If we get here, region is either null (nothing found here) or + // is the non-conflicting region found at the location being requested. + return region; + } + + // String describing name and region location of passed region + private String RegionString(RegionData reg) + { + return String.Format("{0}/{1} at <{2},{3}>", + reg.RegionName, reg.RegionID, reg.coordX, reg.coordY); + } + + // String describing name and region location of passed region + private String RegionString(GridRegion reg) + { + return String.Format("{0}/{1} at <{2},{3}>", + reg.RegionName, reg.RegionID, reg.RegionCoordX, reg.RegionCoordY); + } + public bool DeregisterRegion(UUID regionID) { RegionData region = m_Database.Get(regionID, UUID.Zero); @@ -312,8 +492,10 @@ namespace OpenSim.Services.GridService if (region != null) { // Not really? Maybe? - List rdatas = m_Database.Get(region.posX - (int)Constants.RegionSize - 1, region.posY - (int)Constants.RegionSize - 1, - region.posX + (int)Constants.RegionSize + 1, region.posY + (int)Constants.RegionSize + 1, scopeID); + // The adjacent regions are presumed to be the same size as the current region + List rdatas = m_Database.Get( + region.posX - region.sizeX - 1, region.posY - region.sizeY - 1, + region.posX + region.sizeX + 1, region.posY + region.sizeY + 1, scopeID); foreach (RegionData rdata in rdatas) { @@ -325,7 +507,11 @@ namespace OpenSim.Services.GridService } } -// m_log.DebugFormat("[GRID SERVICE]: region {0} has {1} neighbours", region.RegionName, rinfos.Count); + // string rNames = ""; + // foreach (GridRegion gr in rinfos) + // rNames += gr.RegionName + ","; + // m_log.DebugFormat("{0} region {1} has {2} neighbours ({3})", + // LogHeader, region.RegionName, rinfos.Count, rNames); } else { @@ -346,20 +532,36 @@ namespace OpenSim.Services.GridService return null; } + // Get a region given its base coordinates. + // NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST + // be the base coordinate of the region. + // The snapping is technically unnecessary but is harmless because regions are always + // multiples of the legacy region size (256). public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) { - int snapX = (int)(x / Constants.RegionSize) * (int)Constants.RegionSize; - int snapY = (int)(y / Constants.RegionSize) * (int)Constants.RegionSize; + uint regionX = Util.WorldToRegionLoc((uint)x); + uint regionY = Util.WorldToRegionLoc((uint)y); + int snapX = (int)Util.RegionToWorldLoc(regionX); + int snapY = (int)Util.RegionToWorldLoc(regionY); + RegionData rdata = m_Database.Get(snapX, snapY, scopeID); if (rdata != null) + { + m_log.DebugFormat("{0} GetRegionByPosition. Found region {1} in database. Pos=<{2},{3}>", + LogHeader, rdata.RegionName, regionX, regionY); return RegionData2RegionInfo(rdata); - - return null; + } + else + { + m_log.DebugFormat("{0} GetRegionByPosition. Did not find region in database. Pos=<{1},{2}>", + LogHeader, regionX, regionY); + return null; + } } public GridRegion GetRegionByName(UUID scopeID, string name) { - List rdatas = m_Database.Get(name, scopeID); + List rdatas = m_Database.Get(Util.EscapeForLike(name), scopeID); if ((rdatas != null) && (rdatas.Count > 0)) return RegionData2RegionInfo(rdatas[0]); // get the first @@ -377,7 +579,7 @@ namespace OpenSim.Services.GridService { // m_log.DebugFormat("[GRID SERVICE]: GetRegionsByName {0}", name); - List rdatas = m_Database.Get(name + "%", scopeID); + List rdatas = m_Database.Get(Util.EscapeForLike(name) + "%", scopeID); int count = 0; List rinfos = new List(); @@ -440,6 +642,8 @@ namespace OpenSim.Services.GridService RegionData rdata = new RegionData(); rdata.posX = (int)rinfo.RegionLocX; rdata.posY = (int)rinfo.RegionLocY; + rdata.sizeX = rinfo.RegionSizeX; + rdata.sizeY = rinfo.RegionSizeY; rdata.RegionID = rinfo.RegionID; rdata.RegionName = rinfo.RegionName; rdata.Data = rinfo.ToKeyValuePairs(); @@ -453,6 +657,8 @@ namespace OpenSim.Services.GridService GridRegion rinfo = new GridRegion(rdata.Data); rinfo.RegionLocX = rdata.posX; rinfo.RegionLocY = rdata.posY; + rinfo.RegionSizeX = rdata.sizeX; + rinfo.RegionSizeY = rdata.sizeY; rinfo.RegionID = rdata.RegionID; rinfo.RegionName = rdata.RegionName; rinfo.ScopeID = rdata.ScopeID; @@ -478,6 +684,33 @@ namespace OpenSim.Services.GridService return ret; } + public List GetDefaultHypergridRegions(UUID scopeID) + { + List ret = new List(); + + List regions = m_Database.GetDefaultHypergridRegions(scopeID); + + foreach (RegionData r in regions) + { + if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0) + ret.Add(RegionData2RegionInfo(r)); + } + + int hgDefaultRegionsFoundOnline = regions.Count; + + // For now, hypergrid default regions will always be given precedence but we will also return simple default + // regions in case no specific hypergrid regions are specified. + ret.AddRange(GetDefaultRegions(scopeID)); + + int normalDefaultRegionsFoundOnline = ret.Count - hgDefaultRegionsFoundOnline; + + m_log.DebugFormat( + "[GRID SERVICE]: GetDefaultHypergridRegions returning {0} hypergrid default and {1} normal default regions", + hgDefaultRegionsFoundOnline, normalDefaultRegionsFoundOnline); + + return ret; + } + public List GetFallbackRegions(UUID scopeID, int x, int y) { List ret = new List(); @@ -526,40 +759,41 @@ namespace OpenSim.Services.GridService private void HandleDeregisterRegion(string module, string[] cmd) { - if (cmd.Length != 4) + if (cmd.Length < 4) { - MainConsole.Instance.Output("Syntax: degregister region id "); + MainConsole.Instance.Output("Usage: degregister region id +"); return; } - string rawRegionUuid = cmd[3]; - UUID regionUuid; - - if (!UUID.TryParse(rawRegionUuid, out regionUuid)) + for (int i = 3; i < cmd.Length; i++) { - MainConsole.Instance.OutputFormat("{0} is not a valid region uuid", rawRegionUuid); - return; - } + string rawRegionUuid = cmd[i]; + UUID regionUuid; - GridRegion region = GetRegionByUUID(UUID.Zero, regionUuid); + if (!UUID.TryParse(rawRegionUuid, out regionUuid)) + { + MainConsole.Instance.OutputFormat("{0} is not a valid region uuid", rawRegionUuid); + return; + } - if (region == null) - { - MainConsole.Instance.OutputFormat("No region with UUID {0}", regionUuid); - return; - } + GridRegion region = GetRegionByUUID(UUID.Zero, regionUuid); - if (DeregisterRegion(regionUuid)) - { - MainConsole.Instance.OutputFormat("Deregistered {0} {1}", region.RegionName, regionUuid); - } - else - { - // I don't think this can ever occur if we know that the region exists. - MainConsole.Instance.OutputFormat("Error deregistering {0} {1}", region.RegionName, regionUuid); - } + if (region == null) + { + MainConsole.Instance.OutputFormat("No region with UUID {0}", regionUuid); + return; + } - return; + if (DeregisterRegion(regionUuid)) + { + MainConsole.Instance.OutputFormat("Deregistered {0} {1}", region.RegionName, regionUuid); + } + else + { + // I don't think this can ever occur if we know that the region exists. + MainConsole.Instance.OutputFormat("Error deregistering {0} {1}", region.RegionName, regionUuid); + } + } } private void HandleShowRegions(string module, string[] cmd) @@ -575,6 +809,27 @@ namespace OpenSim.Services.GridService OutputRegionsToConsoleSummary(regions); } + private void HandleShowGridSize(string module, string[] cmd) + { + List regions = m_Database.Get(int.MinValue, int.MinValue, int.MaxValue, int.MaxValue, UUID.Zero); + + double size = 0; + + foreach (RegionData region in regions) + { + int flags = Convert.ToInt32(region.Data["flags"]); + + if ((flags & (int)Framework.RegionFlags.Hyperlink) == 0) + size += region.sizeX * region.sizeY; + } + + MainConsole.Instance.Output("This is a very rough approximation."); + MainConsole.Instance.Output("Although it will not count regions that are actually links to others over the Hypergrid, "); + MainConsole.Instance.Output("it will count regions that are inactive but were not deregistered from the grid service"); + MainConsole.Instance.Output("(e.g. simulator crashed rather than shutting down cleanly).\n"); + + MainConsole.Instance.OutputFormat("Grid size: {0} km squared.", size / 1000000); + } private void HandleShowRegion(string module, string[] cmd) { @@ -586,7 +841,7 @@ namespace OpenSim.Services.GridService string regionName = cmd[3]; - List regions = m_Database.Get(regionName, UUID.Zero); + List regions = m_Database.Get(Util.EscapeForLike(regionName), UUID.Zero); if (regions == null || regions.Count < 1) { MainConsole.Instance.Output("No region with name {0} found", regionName); @@ -604,20 +859,20 @@ namespace OpenSim.Services.GridService return; } - int x, y; - if (!int.TryParse(cmd[3], out x)) + uint x, y; + if (!uint.TryParse(cmd[3], out x)) { MainConsole.Instance.Output("x-coord must be an integer"); return; } - if (!int.TryParse(cmd[4], out y)) + if (!uint.TryParse(cmd[4], out y)) { MainConsole.Instance.Output("y-coord must be an integer"); return; } - RegionData region = m_Database.Get(x * (int)Constants.RegionSize, y * (int)Constants.RegionSize, UUID.Zero); + RegionData region = m_Database.Get((int)Util.RegionToWorldLoc(x), (int)Util.RegionToWorldLoc(y), UUID.Zero); if (region == null) { MainConsole.Instance.OutputFormat("No region found at {0},{1}", x, y); @@ -634,7 +889,8 @@ namespace OpenSim.Services.GridService ConsoleDisplayList dispList = new ConsoleDisplayList(); dispList.AddRow("Region Name", r.RegionName); dispList.AddRow("Region ID", r.RegionID); - dispList.AddRow("Location", string.Format("{0},{1}", r.coordX, r.coordY)); + dispList.AddRow("Position", string.Format("{0},{1}", r.coordX, r.coordY)); + dispList.AddRow("Size", string.Format("{0}x{1}", r.sizeX, r.sizeY)); dispList.AddRow("URI", r.Data["serverURI"]); dispList.AddRow("Owner ID", r.Data["owner_uuid"]); dispList.AddRow("Flags", flags); @@ -651,10 +907,10 @@ namespace OpenSim.Services.GridService private void OutputRegionsToConsoleSummary(List regions) { ConsoleDisplayTable dispTable = new ConsoleDisplayTable(); - dispTable.AddColumn("Name", 16); + dispTable.AddColumn("Name", 44); dispTable.AddColumn("ID", 36); dispTable.AddColumn("Position", 11); - dispTable.AddColumn("Owner ID", 36); + dispTable.AddColumn("Size", 11); dispTable.AddColumn("Flags", 60); foreach (RegionData r in regions) @@ -664,7 +920,7 @@ namespace OpenSim.Services.GridService r.RegionName, r.RegionID.ToString(), string.Format("{0},{1}", r.coordX, r.coordY), - r.Data["owner_uuid"].ToString(), + string.Format("{0}x{1}", r.sizeX, r.sizeY), flags.ToString()); } @@ -716,7 +972,7 @@ namespace OpenSim.Services.GridService return; } - List regions = m_Database.Get(cmd[3], UUID.Zero); + List regions = m_Database.Get(Util.EscapeForLike(cmd[3]), UUID.Zero); if (regions == null || regions.Count < 1) { MainConsole.Instance.Output("Region not found"); @@ -734,5 +990,18 @@ namespace OpenSim.Services.GridService m_Database.Store(r); } } + + /// + /// Gets the grid extra service URls we wish for the region to send in OpenSimExtras to dynamically refresh + /// parameters in the viewer used to access services like map, search and destination guides. + /// see "SimulatorFeaturesModule" + /// + /// + /// The grid extra service URls. + /// + public Dictionary GetExtraFeatures() + { + return m_ExtraFeatures; + } } } diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 7abed20..9d016fc 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -47,7 +47,7 @@ using OpenMetaverse; namespace OpenSim.Services.GridService { - public class HypergridLinker + public class HypergridLinker : IHypergridLinker { private static readonly ILog m_log = LogManager.GetLogger( @@ -63,14 +63,11 @@ namespace OpenSim.Services.GridService protected GatekeeperServiceConnector m_GatekeeperConnector; protected UUID m_ScopeID = UUID.Zero; +// protected bool m_Check4096 = true; protected string m_MapTileDirectory = string.Empty; protected string m_ThisGatekeeper = string.Empty; protected Uri m_ThisGatekeeperURI = null; - // Hyperlink regions are hyperlinks on the map - public readonly Dictionary m_HyperlinkRegions = new Dictionary(); - protected Dictionary m_HyperlinkHandles = new Dictionary(); - protected GridRegion m_DefaultRegion; protected GridRegion DefaultRegion { @@ -78,7 +75,7 @@ namespace OpenSim.Services.GridService { if (m_DefaultRegion == null) { - List defs = m_GridService.GetDefaultRegions(m_ScopeID); + List defs = m_GridService.GetDefaultHypergridRegions(m_ScopeID); if (defs != null && defs.Count > 0) m_DefaultRegion = defs[0]; else @@ -123,9 +120,14 @@ namespace OpenSim.Services.GridService if (scope != string.Empty) UUID.TryParse(scope, out m_ScopeID); +// m_Check4096 = gridConfig.GetBoolean("Check4096", true); + m_MapTileDirectory = gridConfig.GetString("MapTileDirectory", "maptiles"); - m_ThisGatekeeper = gridConfig.GetString("Gatekeeper", string.Empty); + m_ThisGatekeeper = Util.GetConfigVarFromSections(config, "GatekeeperURI", + new string[] { "Startup", "Hypergrid", "GridService" }, String.Empty); + // Legacy. Remove soon! + m_ThisGatekeeper = gridConfig.GetString("Gatekeeper", m_ThisGatekeeper); try { m_ThisGatekeeperURI = new Uri(m_ThisGatekeeper); @@ -154,18 +156,18 @@ namespace OpenSim.Services.GridService if (MainConsole.Instance != null) { - MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region", + MainConsole.Instance.Commands.AddCommand("Hypergrid", false, "link-region", "link-region []", "Link a HyperGrid Region. Examples for : http://grid.net:8002/ or http://example.org/path/foo.php", RunCommand); - MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region", + MainConsole.Instance.Commands.AddCommand("Hypergrid", false, "link-region", "link-region []", "Link a hypergrid region (deprecated)", RunCommand); - MainConsole.Instance.Commands.AddCommand("hypergrid", false, "unlink-region", + MainConsole.Instance.Commands.AddCommand("Hypergrid", false, "unlink-region", "unlink-region ", "Unlink a hypergrid region", RunCommand); - MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-mapping", "link-mapping [ ]", + MainConsole.Instance.Commands.AddCommand("Hypergrid", false, "link-mapping", "link-mapping [ ]", "Set local coordinate to map HG regions to", RunCommand); - MainConsole.Instance.Commands.AddCommand("hypergrid", false, "show hyperlinks", "show hyperlinks", + MainConsole.Instance.Commands.AddCommand("Hypergrid", false, "show hyperlinks", "show hyperlinks", "List the HG regions", HandleShow); } } @@ -177,14 +179,14 @@ namespace OpenSim.Services.GridService public GridRegion LinkRegion(UUID scopeID, string regionDescriptor) { string reason = string.Empty; - int xloc = random.Next(0, Int16.MaxValue) * (int)Constants.RegionSize; - return TryLinkRegionToCoords(scopeID, regionDescriptor, xloc, 0, out reason); + uint xloc = Util.RegionToWorldLoc((uint)random.Next(0, Int16.MaxValue)); + return TryLinkRegionToCoords(scopeID, regionDescriptor, (int)xloc, 0, out reason); } private static Random random = new Random(); // From the command line link-region (obsolete) and the map - public GridRegion TryLinkRegionToCoords(UUID scopeID, string mapName, int xloc, int yloc, out string reason) + private GridRegion TryLinkRegionToCoords(UUID scopeID, string mapName, int xloc, int yloc, out string reason) { return TryLinkRegionToCoords(scopeID, mapName, xloc, yloc, UUID.Zero, out reason); } @@ -194,24 +196,36 @@ namespace OpenSim.Services.GridService reason = string.Empty; GridRegion regInfo = null; + mapName = mapName.Trim(); + if (!mapName.StartsWith("http")) { - string host = "127.0.0.1"; - string portstr; + // Formats: grid.example.com:8002:region name + // grid.example.com:region name + // grid.example.com:8002 + // grid.example.com + + string host; + uint port = 80; string regionName = ""; - uint port = 0; + string[] parts = mapName.Split(new char[] { ':' }); - if (parts.Length >= 1) + + if (parts.Length == 0) { - host = parts[0]; + reason = "Wrong format for link-region"; + return null; } + + host = parts[0]; + if (parts.Length >= 2) { - portstr = parts[1]; - //m_log.Debug("-- port = " + portstr); - if (!UInt32.TryParse(portstr, out port)) + // If it's a number then assume it's a port. Otherwise, it's a region name. + if (!UInt32.TryParse(parts[1], out port)) regionName = parts[1]; } + // always take the last one if (parts.Length >= 3) { @@ -228,14 +242,30 @@ namespace OpenSim.Services.GridService } else { - string[] parts = mapName.Split(new char[] {' '}); - string regionName = String.Empty; - if (parts.Length > 1) + // Formats: http://grid.example.com region name + // http://grid.example.com "region name" + // http://grid.example.com + + string serverURI; + string regionName = ""; + + string[] parts = mapName.Split(new char[] { ' ' }); + + if (parts.Length == 0) { - regionName = mapName.Substring(parts[0].Length + 1); - regionName = regionName.Trim(new char[] {'"'}); + reason = "Wrong format for link-region"; + return null; } - if (TryCreateLink(scopeID, xloc, yloc, regionName, 0, null, parts[0], ownerID, out regInfo, out reason)) + + serverURI = parts[0]; + + if (parts.Length >= 2) + { + regionName = mapName.Substring(serverURI.Length); + regionName = regionName.Trim(new char[] { '"', ' ' }); + } + + if (TryCreateLink(scopeID, xloc, yloc, regionName, 0, null, serverURI, ownerID, out regInfo, out reason)) { regInfo.RegionName = mapName; return regInfo; @@ -244,31 +274,39 @@ namespace OpenSim.Services.GridService return null; } - - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string remoteRegionName, uint externalPort, string externalHostName, UUID ownerID, out GridRegion regInfo, out string reason) + + private bool TryCreateLink(UUID scopeID, int xloc, int yloc, string remoteRegionName, uint externalPort, string externalHostName, UUID ownerID, out GridRegion regInfo, out string reason) { return TryCreateLink(scopeID, xloc, yloc, remoteRegionName, externalPort, externalHostName, null, ownerID, out regInfo, out reason); } - - public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string remoteRegionName, uint externalPort, string externalHostName, string serverURI, UUID ownerID, out GridRegion regInfo, out string reason) + + private bool TryCreateLink(UUID scopeID, int xloc, int yloc, string remoteRegionName, uint externalPort, string externalHostName, string serverURI, UUID ownerID, out GridRegion regInfo, out string reason) { - m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0} {1}, in {2}-{3}", + lock (this) + { + return TryCreateLinkImpl(scopeID, xloc, yloc, remoteRegionName, externalPort, externalHostName, serverURI, ownerID, out regInfo, out reason); + } + } + + private bool TryCreateLinkImpl(UUID scopeID, int xloc, int yloc, string remoteRegionName, uint externalPort, string externalHostName, string serverURI, UUID ownerID, out GridRegion regInfo, out string reason) + { + m_log.InfoFormat("[HYPERGRID LINKER]: Link to {0} {1}, in <{2},{3}>", ((serverURI == null) ? (externalHostName + ":" + externalPort) : serverURI), - remoteRegionName, xloc / Constants.RegionSize, yloc / Constants.RegionSize); + remoteRegionName, Util.WorldToRegionLoc((uint)xloc), Util.WorldToRegionLoc((uint)yloc)); reason = string.Empty; Uri uri = null; regInfo = new GridRegion(); - if ( externalPort > 0) + if (externalPort > 0) regInfo.HttpPort = externalPort; else - regInfo.HttpPort = 0; - if ( externalHostName != null) + regInfo.HttpPort = 80; + if (externalHostName != null) regInfo.ExternalHostName = externalHostName; else regInfo.ExternalHostName = "0.0.0.0"; - if ( serverURI != null) + if (serverURI != null) { regInfo.ServerURI = serverURI; try @@ -280,7 +318,7 @@ namespace OpenSim.Services.GridService catch {} } - if ( remoteRegionName != string.Empty ) + if (remoteRegionName != string.Empty) regInfo.RegionName = remoteRegionName; regInfo.RegionLocX = xloc; @@ -293,6 +331,7 @@ namespace OpenSim.Services.GridService { if (regInfo.ExternalHostName == m_ThisGatekeeperURI.Host && regInfo.HttpPort == m_ThisGatekeeperURI.Port) { + m_log.InfoFormat("[HYPERGRID LINKER]: Cannot hyperlink to regions on the same grid"); reason = "Cannot hyperlink to regions on the same grid"; return false; } @@ -304,8 +343,8 @@ namespace OpenSim.Services.GridService GridRegion region = m_GridService.GetRegionByPosition(regInfo.ScopeID, regInfo.RegionLocX, regInfo.RegionLocY); if (region != null) { - m_log.WarnFormat("[HYPERGRID LINKER]: Coordinates {0}-{1} are already occupied by region {2} with uuid {3}", - regInfo.RegionLocX / Constants.RegionSize, regInfo.RegionLocY / Constants.RegionSize, + m_log.WarnFormat("[HYPERGRID LINKER]: Coordinates <{0},{1}> are already occupied by region {2} with uuid {3}", + Util.WorldToRegionLoc((uint)regInfo.RegionLocX), Util.WorldToRegionLoc((uint)regInfo.RegionLocY), region.RegionName, region.RegionID); reason = "Coordinates are already in use"; return false; @@ -340,12 +379,25 @@ namespace OpenSim.Services.GridService region = m_GridService.GetRegionByUUID(scopeID, regionID); if (region != null) { - m_log.DebugFormat("[HYPERGRID LINKER]: Region already exists in coordinates {0} {1}", - region.RegionLocX / Constants.RegionSize, region.RegionLocY / Constants.RegionSize); + m_log.DebugFormat("[HYPERGRID LINKER]: Region already exists in coordinates <{0},{1}>", + Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY)); regInfo = region; return true; } + // We are now performing this check for each individual teleport in the EntityTransferModule instead. This + // allows us to give better feedback when teleports fail because of the distance reason (which can't be + // done here) and it also hypergrid teleports that are within range (possibly because the source grid + // itself has regions that are very far apart). +// uint x, y; +// if (m_Check4096 && !Check4096(handle, out x, out y)) +// { +// //RemoveHyperlinkRegion(regInfo.RegionID); +// reason = "Region is too far (" + x + ", " + y + ")"; +// m_log.Info("[HYPERGRID LINKER]: Unable to link, region is too far (" + x + ", " + y + ")"); +// //return false; +// } + regInfo.RegionID = regionID; if (externalName == string.Empty) @@ -362,7 +414,8 @@ namespace OpenSim.Services.GridService regInfo.RegionSecret = handle.ToString(); AddHyperlinkRegion(regInfo, handle); - m_log.InfoFormat("[HYPERGRID LINKER]: Successfully linked to region {0} with image {1}", regInfo.RegionName, regInfo.TerrainImage); + m_log.InfoFormat("[HYPERGRID LINKER]: Successfully linked to region {0} at <{1},{2}> with image {3}", + regInfo.RegionName, Util.WorldToRegionLoc((uint)regInfo.RegionLocX), Util.WorldToRegionLoc((uint)regInfo.RegionLocY), regInfo.TerrainImage); return true; } @@ -371,7 +424,7 @@ namespace OpenSim.Services.GridService m_log.DebugFormat("[HYPERGRID LINKER]: Request to unlink {0}", mapName); GridRegion regInfo = null; - List regions = m_Database.Get(mapName, m_ScopeID); + List regions = m_Database.Get(Util.EscapeForLike(mapName), m_ScopeID); if (regions != null && regions.Count > 0) { OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]); @@ -395,6 +448,52 @@ namespace OpenSim.Services.GridService } } +// Not currently used +// /// +// /// Cope with this viewer limitation. +// /// +// /// +// /// +// public bool Check4096(ulong realHandle, out uint x, out uint y) +// { +// uint ux = 0, uy = 0; +// Utils.LongToUInts(realHandle, out ux, out uy); +// x = Util.WorldToRegionLoc(ux); +// y = Util.WorldToRegionLoc(uy); +// +// const uint limit = Util.RegionToWorldLoc(4096 - 1); +// uint xmin = ux - limit; +// uint xmax = ux + limit; +// uint ymin = uy - limit; +// uint ymax = uy + limit; +// // World map boundary checks +// if (xmin < 0 || xmin > ux) +// xmin = 0; +// if (xmax > int.MaxValue || xmax < ux) +// xmax = int.MaxValue; +// if (ymin < 0 || ymin > uy) +// ymin = 0; +// if (ymax > int.MaxValue || ymax < uy) +// ymax = int.MaxValue; +// +// // Check for any regions that are within the possible teleport range to the linked region +// List regions = m_GridService.GetRegionRange(m_ScopeID, (int)xmin, (int)xmax, (int)ymin, (int)ymax); +// if (regions.Count == 0) +// { +// return false; +// } +// else +// { +// // Check for regions which are not linked regions +// List hyperlinks = m_GridService.GetHyperlinks(m_ScopeID); +// IEnumerable availableRegions = regions.Except(hyperlinks); +// if (availableRegions.Count() == 0) +// return false; +// } +// +// return true; +// } + private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle) { RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo); @@ -437,9 +536,14 @@ namespace OpenSim.Services.GridService MainConsole.Instance.Output(new string('-', 72)); foreach (RegionData r in regions) { - MainConsole.Instance.Output(String.Format("{0}\n{2,-32} {1}\n", - r.RegionName, r.RegionID, String.Format("{0},{1} ({2},{3})", r.posX, r.posY, - r.posX / Constants.RegionSize, r.posY / Constants.RegionSize))); + MainConsole.Instance.Output( + String.Format("{0}\n{2,-32} {1}\n", + r.RegionName, r.RegionID, + String.Format("{0},{1} ({2},{3})", r.posX, r.posY, + Util.WorldToRegionLoc((uint)r.posX), Util.WorldToRegionLoc((uint)r.posY) + ) + ) + ); } return; } @@ -464,8 +568,8 @@ namespace OpenSim.Services.GridService int xloc, yloc; string serverURI; string remoteName = null; - xloc = Convert.ToInt32(cmdparams[0]) * (int)Constants.RegionSize; - yloc = Convert.ToInt32(cmdparams[1]) * (int)Constants.RegionSize; + xloc = (int)Util.RegionToWorldLoc((uint)Convert.ToInt32(cmdparams[0])); + yloc = (int)Util.RegionToWorldLoc((uint)Convert.ToInt32(cmdparams[1])); serverURI = cmdparams[2]; if (cmdparams.Length > 3) remoteName = string.Join(" ", cmdparams, 3, cmdparams.Length - 3); @@ -536,13 +640,13 @@ namespace OpenSim.Services.GridService { // old format GridRegion regInfo; - int xloc, yloc; + uint xloc, yloc; uint externalPort; string externalHostName; try { - xloc = Convert.ToInt32(cmdparams[0]); - yloc = Convert.ToInt32(cmdparams[1]); + xloc = Convert.ToUInt32(cmdparams[0]); + yloc = Convert.ToUInt32(cmdparams[1]); externalPort = Convert.ToUInt32(cmdparams[3]); externalHostName = cmdparams[2]; //internalPort = Convert.ToUInt32(cmdparams[4]); @@ -556,10 +660,11 @@ namespace OpenSim.Services.GridService } // Convert cell coordinates given by the user to meters - xloc = xloc * (int)Constants.RegionSize; - yloc = yloc * (int)Constants.RegionSize; + xloc = Util.RegionToWorldLoc(xloc); + yloc = Util.RegionToWorldLoc(yloc); string reason = string.Empty; - if (TryCreateLink(UUID.Zero, xloc, yloc, string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason)) + if (TryCreateLink(UUID.Zero, (int)xloc, (int)yloc, + string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason)) { // What is this? The GridRegion instance will be discarded anyway, // which effectively ignores any local name given with the command. @@ -639,13 +744,13 @@ namespace OpenSim.Services.GridService private void ReadLinkFromConfig(IConfig config) { GridRegion regInfo; - int xloc, yloc; + uint xloc, yloc; uint externalPort; string externalHostName; uint realXLoc, realYLoc; - xloc = Convert.ToInt32(config.GetString("xloc", "0")); - yloc = Convert.ToInt32(config.GetString("yloc", "0")); + xloc = Convert.ToUInt32(config.GetString("xloc", "0")); + yloc = Convert.ToUInt32(config.GetString("yloc", "0")); externalPort = Convert.ToUInt32(config.GetString("externalPort", "0")); externalHostName = config.GetString("externalHostName", ""); realXLoc = Convert.ToUInt32(config.GetString("real-xloc", "0")); @@ -653,18 +758,19 @@ namespace OpenSim.Services.GridService if (m_enableAutoMapping) { - xloc = (int)((xloc % 100) + m_autoMappingX); - yloc = (int)((yloc % 100) + m_autoMappingY); + xloc = (xloc % 100) + m_autoMappingX; + yloc = (yloc % 100) + m_autoMappingY; } if (((realXLoc == 0) && (realYLoc == 0)) || (((realXLoc - xloc < 3896) || (xloc - realXLoc < 3896)) && ((realYLoc - yloc < 3896) || (yloc - realYLoc < 3896)))) { - xloc = xloc * (int)Constants.RegionSize; - yloc = yloc * (int)Constants.RegionSize; + xloc = Util.RegionToWorldLoc(xloc); + yloc = Util.RegionToWorldLoc(yloc); string reason = string.Empty; - if (TryCreateLink(UUID.Zero, xloc, yloc, string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason)) + if (TryCreateLink(UUID.Zero, (int)xloc, (int)yloc, + string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason)) { regInfo.RegionName = config.GetString("localName", ""); } diff --git a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs index 5c0c8f4..0841e5a 100644 --- a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs index 7b84d55..8e10125 100644 --- a/OpenSim/Services/HypergridService/GatekeeperService.cs +++ b/OpenSim/Services/HypergridService/GatekeeperService.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -58,6 +58,7 @@ namespace OpenSim.Services.HypergridService private static IUserAgentService m_UserAgentService; private static ISimulationService m_SimulationService; private static IGridUserService m_GridUserService; + private static IBansService m_BansService; private static string m_AllowedClients = string.Empty; private static string m_DeniedClients = string.Empty; @@ -87,6 +88,7 @@ namespace OpenSim.Services.HypergridService string presenceService = serverConfig.GetString("PresenceService", String.Empty); string simulationService = serverConfig.GetString("SimulationService", String.Empty); string gridUserService = serverConfig.GetString("GridUserService", String.Empty); + string bansService = serverConfig.GetString("BansService", String.Empty); // These are mandatory, the others aren't if (gridService == string.Empty || presenceService == string.Empty) @@ -96,7 +98,9 @@ namespace OpenSim.Services.HypergridService UUID.TryParse(scope, out m_ScopeID); //m_WelcomeMessage = serverConfig.GetString("WelcomeMessage", "Welcome to OpenSim!"); m_AllowTeleportsToAnyRegion = serverConfig.GetBoolean("AllowTeleportsToAnyRegion", true); - m_ExternalName = serverConfig.GetString("ExternalName", string.Empty); + m_ExternalName = Util.GetConfigVarFromSections(config, "GatekeeperURI", + new string[] { "Startup", "Hypergrid", "GatekeeperService" }, String.Empty); + m_ExternalName = serverConfig.GetString("ExternalName", m_ExternalName); if (m_ExternalName != string.Empty && !m_ExternalName.EndsWith("/")) m_ExternalName = m_ExternalName + "/"; @@ -119,14 +123,19 @@ namespace OpenSim.Services.HypergridService m_UserAgentService = ServerUtils.LoadPlugin(homeUsersService, args); if (gridUserService != string.Empty) m_GridUserService = ServerUtils.LoadPlugin(gridUserService, args); + if (bansService != string.Empty) + m_BansService = ServerUtils.LoadPlugin(bansService, args); if (simService != null) m_SimulationService = simService; else if (simulationService != string.Empty) m_SimulationService = ServerUtils.LoadPlugin(simulationService, args); - m_AllowedClients = serverConfig.GetString("AllowedClients", string.Empty); - m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty); + string[] possibleAccessControlConfigSections = new string[] { "AccessControl", "GatekeeperService" }; + m_AllowedClients = Util.GetConfigVarFromSections( + config, "AllowedClients", possibleAccessControlConfigSections, string.Empty); + m_DeniedClients = Util.GetConfigVarFromSections( + config, "DeniedClients", possibleAccessControlConfigSections, string.Empty); m_ForeignAgentsAllowed = serverConfig.GetBoolean("ForeignAgentsAllowed", true); LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_ForeignsAllowedExceptions); @@ -165,7 +174,7 @@ namespace OpenSim.Services.HypergridService m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to link to {0}", (regionName == string.Empty)? "default region" : regionName); if (!m_AllowTeleportsToAnyRegion || regionName == string.Empty) { - List defs = m_GridService.GetDefaultRegions(m_ScopeID); + List defs = m_GridService.GetDefaultHypergridRegions(m_ScopeID); if (defs != null && defs.Count > 0) { region = defs[0]; @@ -198,41 +207,75 @@ namespace OpenSim.Services.HypergridService return true; } - public GridRegion GetHyperlinkRegion(UUID regionID) + public GridRegion GetHyperlinkRegion(UUID regionID, UUID agentID, string agentHomeURI, out string message) { - m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to get hyperlink region {0}", regionID); + message = null; if (!m_AllowTeleportsToAnyRegion) + { // Don't even check the given regionID + m_log.DebugFormat( + "[GATEKEEPER SERVICE]: Returning gateway region {0} {1} @ {2} to user {3}{4} as teleporting to arbitrary regions is not allowed.", + m_DefaultGatewayRegion.RegionName, + m_DefaultGatewayRegion.RegionID, + m_DefaultGatewayRegion.ServerURI, + agentID, + agentHomeURI == null ? "" : " @ " + agentHomeURI); + + message = "Teleporting to the default region."; return m_DefaultGatewayRegion; + } GridRegion region = m_GridService.GetRegionByUUID(m_ScopeID, regionID); + + if (region == null) + { + m_log.DebugFormat( + "[GATEKEEPER SERVICE]: Could not find region with ID {0} as requested by user {1}{2}. Returning null.", + regionID, agentID, (agentHomeURI == null) ? "" : " @ " + agentHomeURI); + + message = "The teleport destination could not be found."; + return null; + } + + m_log.DebugFormat( + "[GATEKEEPER SERVICE]: Returning region {0} {1} @ {2} to user {3}{4}.", + region.RegionName, + region.RegionID, + region.ServerURI, + agentID, + agentHomeURI == null ? "" : " @ " + agentHomeURI); + return region; } #region Login Agent - public bool LoginAgent(AgentCircuitData aCircuit, GridRegion destination, out string reason) + public bool LoginAgent(GridRegion source, AgentCircuitData aCircuit, GridRegion destination, out string reason) { reason = string.Empty; string authURL = string.Empty; if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) authURL = aCircuit.ServiceURLs["HomeURI"].ToString(); - m_log.InfoFormat("[GATEKEEPER SERVICE]: Login request for {0} {1} @ {2} ({3}) at {4} using viewer {5}, channel {6}, IP {7}, Mac {8}, Id0 {9} Teleport Flags {10}", - aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName, - aCircuit.Viewer, aCircuit.Channel, aCircuit.IPAddress, aCircuit.Mac, aCircuit.Id0, aCircuit.teleportFlags.ToString()); - + + m_log.InfoFormat("[GATEKEEPER SERVICE]: Login request for {0} {1} @ {2} ({3}) at {4} using viewer {5}, channel {6}, IP {7}, Mac {8}, Id0 {9}, Teleport Flags: {10}. From region {11}", + aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionID, + aCircuit.Viewer, aCircuit.Channel, aCircuit.IPAddress, aCircuit.Mac, aCircuit.Id0, (TeleportFlags)aCircuit.teleportFlags, + (source == null) ? "Unknown" : string.Format("{0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI)); + + string curViewer = Util.GetViewerName(aCircuit); + // // Check client // if (m_AllowedClients != string.Empty) { Regex arx = new Regex(m_AllowedClients); - Match am = arx.Match(aCircuit.Viewer); + Match am = arx.Match(curViewer); if (!am.Success) { - m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is not allowed", aCircuit.Viewer); + m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is not allowed", curViewer); return false; } } @@ -240,11 +283,11 @@ namespace OpenSim.Services.HypergridService if (m_DeniedClients != string.Empty) { Regex drx = new Regex(m_DeniedClients); - Match dm = drx.Match(aCircuit.Viewer); + Match dm = drx.Match(curViewer); if (dm.Success) { - m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is denied", aCircuit.Viewer); + m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is denied", curViewer); return false; } } @@ -285,17 +328,16 @@ namespace OpenSim.Services.HypergridService } } } - m_log.DebugFormat("[GATEKEEPER SERVICE]: User is ok"); // // Foreign agents allowed? Exceptions? // - if (account == null) + if (account == null) { bool allowed = m_ForeignAgentsAllowed; if (m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsAllowedExceptions)) - allowed = false; + allowed = false; if (!m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsDisallowedExceptions)) allowed = true; @@ -309,6 +351,20 @@ namespace OpenSim.Services.HypergridService } } + // + // Is the user banned? + // This uses a Ban service that's more powerful than the configs + // + string uui = (account != null ? aCircuit.AgentID.ToString() : Util.ProduceUserUniversalIdentifier(aCircuit)); + if (m_BansService != null && m_BansService.IsBanned(uui, aCircuit.IPAddress, aCircuit.Id0, authURL)) + { + reason = "You are banned from this world"; + m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: user {0} is banned", uui); + return false; + } + + m_log.DebugFormat("[GATEKEEPER SERVICE]: User {0} is ok", aCircuit.Name); + bool isFirstLogin = false; // // Login the presence, if it's not there yet (by the login service) @@ -326,7 +382,8 @@ namespace OpenSim.Services.HypergridService aCircuit.firstname, aCircuit.lastname); return false; } - m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok"); + + m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence {0} is ok", aCircuit.Name); // Also login foreigners with GridUser service if (m_GridUserService != null && account == null) @@ -357,7 +414,9 @@ namespace OpenSim.Services.HypergridService reason = "Destination region not found"; return false; } - m_log.DebugFormat("[GATEKEEPER SERVICE]: destination ok: {0}", destination.RegionName); + + m_log.DebugFormat( + "[GATEKEEPER SERVICE]: Destination {0} is ok for {1}", destination.RegionName, aCircuit.Name); // // Adjust the visible name @@ -374,7 +433,7 @@ namespace OpenSim.Services.HypergridService try { Uri uri = new Uri(aCircuit.ServiceURLs["HomeURI"].ToString()); - aCircuit.lastname = "@" + uri.Host; // + ":" + uri.Port; + aCircuit.lastname = "@" + uri.Authority; } catch { @@ -391,8 +450,16 @@ namespace OpenSim.Services.HypergridService // Preserve our TeleportFlags we have gathered so-far loginFlag |= (Constants.TeleportFlags) aCircuit.teleportFlags; - m_log.DebugFormat("[GATEKEEPER SERVICE]: launching agent {0}", loginFlag); - return m_SimulationService.CreateAgent(destination, aCircuit, (uint)loginFlag, out reason); + m_log.DebugFormat("[GATEKEEPER SERVICE]: Launching {0}, Teleport Flags: {1}", aCircuit.Name, loginFlag); + + EntityTransferContext ctx = new EntityTransferContext(); + + if (!m_SimulationService.QueryAccess( + destination, aCircuit.AgentID, aCircuit.ServiceURLs["HomeURI"].ToString(), + true, aCircuit.startpos, new List(), ctx, out reason)) + return false; + + return m_SimulationService.CreateAgent(source, destination, aCircuit, (uint)loginFlag, out reason); } protected bool Authenticate(AgentCircuitData aCircuit) @@ -400,6 +467,12 @@ namespace OpenSim.Services.HypergridService if (!CheckAddress(aCircuit.ServiceSessionID)) return false; + if (string.IsNullOrEmpty(aCircuit.IPAddress)) + { + m_log.DebugFormat("[GATEKEEPER SERVICE]: Agent did not provide a client IP address."); + return false; + } + string userURL = string.Empty; if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) userURL = aCircuit.ServiceURLs["HomeURI"].ToString(); diff --git a/OpenSim/Services/HypergridService/HGAssetService.cs b/OpenSim/Services/HypergridService/HGAssetService.cs index 84dec8d..b83fb1e 100644 --- a/OpenSim/Services/HypergridService/HGAssetService.cs +++ b/OpenSim/Services/HypergridService/HGAssetService.cs @@ -76,10 +76,10 @@ namespace OpenSim.Services.HypergridService if (m_UserAccountService == null) throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); - // legacy configuration [obsolete] - m_HomeURL = assetConfig.GetString("ProfileServerURI", string.Empty); - // Preferred - m_HomeURL = assetConfig.GetString("HomeURI", m_HomeURL); + m_HomeURL = Util.GetConfigVarFromSections(config, "HomeURI", + new string[] { "Startup", "Hypergrid", configName }, string.Empty); + if (m_HomeURL == string.Empty) + throw new Exception("[HGAssetService] No HomeURI specified"); m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); @@ -100,7 +100,7 @@ namespace OpenSim.Services.HypergridService return null; if (asset.Metadata.Type == (sbyte)AssetType.Object) - asset.Data = AdjustIdentifiers(asset.Data); ; + asset.Data = AdjustIdentifiers(asset.Data); AdjustIdentifiers(asset.Metadata); @@ -129,6 +129,14 @@ namespace OpenSim.Services.HypergridService if (!m_AssetPerms.AllowedExport(asset.Type)) return null; + // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) + // Fix bad assets before sending them elsewhere + if (asset.Type == (int)AssetType.Object && asset.Data != null) + { + string xml = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(asset.Data)); + asset.Data = Utils.StringToBytes(xml); + } + return asset.Data; } @@ -139,6 +147,14 @@ namespace OpenSim.Services.HypergridService if (!m_AssetPerms.AllowedImport(asset.Type)) return string.Empty; + // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) + // Fix bad assets before storing on this server + if (asset.Type == (int)AssetType.Object && asset.Data != null) + { + string xml = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(asset.Data)); + asset.Data = Utils.StringToBytes(xml); + } + return base.Store(asset); } @@ -160,10 +176,16 @@ namespace OpenSim.Services.HypergridService meta.CreatorID = meta.CreatorID + ";" + m_HomeURL + "/" + creator.FirstName + " " + creator.LastName; } + // Only for Object protected byte[] AdjustIdentifiers(byte[] data) { string xml = Utils.BytesToString(data); - return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, m_HomeURL, m_Cache, UUID.Zero)); + + // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) + // Fix bad assets before sending them elsewhere + xml = ExternalRepresentationUtils.SanitizeXml(xml); + + return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, "HGAssetService", m_HomeURL, m_Cache, UUID.Zero)); } } diff --git a/OpenSim/Services/HypergridService/HGFSAssetService.cs b/OpenSim/Services/HypergridService/HGFSAssetService.cs new file mode 100644 index 0000000..54e8ccb --- /dev/null +++ b/OpenSim/Services/HypergridService/HGFSAssetService.cs @@ -0,0 +1,189 @@ +/* + * 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 OpenSimulator 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.Reflection; + +using Nini.Config; +using log4net; +using OpenMetaverse; + +using OpenSim.Framework; +using OpenSim.Framework.Serialization.External; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Services.FSAssetService; + +namespace OpenSim.Services.HypergridService +{ + /// + /// Hypergrid asset service. It serves the IAssetService interface, + /// but implements it in ways that are appropriate for inter-grid + /// asset exchanges. This version is for FSAssets. + /// + public class HGFSAssetService : FSAssetConnector, IAssetService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_HomeURL; + private IUserAccountService m_UserAccountService; + + private UserAccountCache m_Cache; + + private AssetPermissions m_AssetPerms; + + public HGFSAssetService(IConfigSource config, string configName) : base(config, "AssetService") + { + m_log.Debug("[HGAsset Service]: Starting in FSAsset mode"); + IConfig assetConfig = config.Configs[configName]; + if (assetConfig == null) + throw new Exception("No HGAssetService configuration"); + + string userAccountsDll = assetConfig.GetString("UserAccountsService", string.Empty); + if (userAccountsDll == string.Empty) + throw new Exception("Please specify UserAccountsService in HGAssetService configuration"); + + Object[] args = new Object[] { config }; + m_UserAccountService = ServerUtils.LoadPlugin(userAccountsDll, args); + if (m_UserAccountService == null) + throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); + + m_HomeURL = Util.GetConfigVarFromSections(config, "HomeURI", + new string[] { "Startup", "Hypergrid", configName }, string.Empty); + if (m_HomeURL == string.Empty) + throw new Exception("[HGAssetService] No HomeURI specified"); + + m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); + + // Permissions + m_AssetPerms = new AssetPermissions(assetConfig); + } + + #region IAssetService overrides + public override AssetBase Get(string id) + { + AssetBase asset = base.Get(id); + + if (asset == null) + return null; + + if (!m_AssetPerms.AllowedExport(asset.Type)) + return null; + + if (asset.Metadata.Type == (sbyte)AssetType.Object) + asset.Data = AdjustIdentifiers(asset.Data); + + AdjustIdentifiers(asset.Metadata); + + return asset; + } + + public override AssetMetadata GetMetadata(string id) + { + AssetMetadata meta = base.GetMetadata(id); + + if (meta == null) + return null; + + AdjustIdentifiers(meta); + + return meta; + } + + public override byte[] GetData(string id) + { + AssetBase asset = Get(id); + + if (asset == null) + return null; + + if (!m_AssetPerms.AllowedExport(asset.Type)) + return null; + + // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) + // Fix bad assets before sending them elsewhere + if (asset.Type == (int)AssetType.Object && asset.Data != null) + { + string xml = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(asset.Data)); + asset.Data = Utils.StringToBytes(xml); + } + + return asset.Data; + } + + //public virtual bool Get(string id, Object sender, AssetRetrieved handler) + + public override string Store(AssetBase asset) + { + if (!m_AssetPerms.AllowedImport(asset.Type)) + return string.Empty; + + // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) + // Fix bad assets before storing on this server + if (asset.Type == (int)AssetType.Object && asset.Data != null) + { + string xml = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(asset.Data)); + asset.Data = Utils.StringToBytes(xml); + } + + return base.Store(asset); + } + + public override bool Delete(string id) + { + // NOGO + return false; + } + + #endregion + + protected void AdjustIdentifiers(AssetMetadata meta) + { + if (meta == null || m_Cache == null) + return; + + UserAccount creator = m_Cache.GetUser(meta.CreatorID); + if (creator != null) + meta.CreatorID = meta.CreatorID + ";" + m_HomeURL + "/" + creator.FirstName + " " + creator.LastName; + } + + // Only for Object + protected byte[] AdjustIdentifiers(byte[] data) + { + string xml = Utils.BytesToString(data); + + // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) + // Fix bad assets before sending them elsewhere + xml = ExternalRepresentationUtils.SanitizeXml(xml); + + return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, "HGAssetService", m_HomeURL, m_Cache, UUID.Zero)); + } + + } + +} diff --git a/OpenSim/Services/HypergridService/HGFriendsService.cs b/OpenSim/Services/HypergridService/HGFriendsService.cs index a8bcfb2..6e35a88 100644 --- a/OpenSim/Services/HypergridService/HGFriendsService.cs +++ b/OpenSim/Services/HypergridService/HGFriendsService.cs @@ -198,7 +198,8 @@ namespace OpenSim.Services.HypergridService // So let's send back the call, but start a thread to continue // with the verification and the actual action. - Util.FireAndForget(delegate { ProcessFriendshipOffered(fromID, fromName, toID, message); }); + Util.FireAndForget( + o => ProcessFriendshipOffered(fromID, fromName, toID, message), null, "HGFriendsService.ProcessFriendshipOffered"); return true; } diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index e8d7cca..32ca09a 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -101,7 +101,14 @@ namespace OpenSim.Services.HypergridService Object[] args = new Object[] { config }; m_GridService = ServerUtils.LoadPlugin(gridService, args); m_PresenceService = ServerUtils.LoadPlugin(presenceService, args); - m_UserAgentService = ServerUtils.LoadPlugin(userAgentService, args); + try + { + m_UserAgentService = ServerUtils.LoadPlugin(userAgentService, args); + } + catch + { + m_log.WarnFormat("[HG IM SERVICE]: Unable to create User Agent Service. Missing config var in [HGInstantMessageService]?"); + } m_RegionCache = new ExpiringCache(); @@ -215,7 +222,15 @@ namespace OpenSim.Services.HypergridService { // Let's check with the UAS if the user is elsewhere m_log.DebugFormat("[HG IM SERVICE]: User is not present. Checking location with User Agent service"); - url = m_UserAgentService.LocateUser(toAgentID); + try + { + url = m_UserAgentService.LocateUser(toAgentID); + } + catch (Exception e) + { + m_log.Warn("[HG IM SERVICE]: LocateUser call failed ", e); + url = string.Empty; + } } // check if we've tried this before.. diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs index 2e9bd40..9158b41 100644 --- a/OpenSim/Services/HypergridService/HGInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGInventoryService.cs @@ -81,10 +81,8 @@ namespace OpenSim.Services.HypergridService if (m_UserAccountService == null) throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); - // legacy configuration [obsolete] - m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty); - // Preferred - m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL); + m_HomeURL = Util.GetConfigVarFromSections(config, "HomeURI", + new string[] { "Startup", "Hypergrid", m_ConfigName }, String.Empty); m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); } @@ -105,12 +103,6 @@ namespace OpenSim.Services.HypergridService return new List(); } - public override InventoryCollection GetUserInventory(UUID userID) - { - // NOGO for this inventory service - return null; - } - public override InventoryFolderBase GetRootFolder(UUID principalID) { //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetRootFolder for {0}", principalID); @@ -123,7 +115,7 @@ namespace OpenSim.Services.HypergridService return ConvertToOpenSim(folders[0]); // make one - XInventoryFolder suitcase = CreateFolder(principalID, UUID.Zero, (int)AssetType.Folder, "My Suitcase"); + XInventoryFolder suitcase = CreateFolder(principalID, UUID.Zero, (int)FolderType.Suitcase, "My Suitcase"); return ConvertToOpenSim(suitcase); } @@ -149,7 +141,7 @@ namespace OpenSim.Services.HypergridService //} - public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) + public override InventoryFolderBase GetFolderForType(UUID principalID, FolderType type) { //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type); return GetRootFolder(principalID); @@ -161,7 +153,14 @@ namespace OpenSim.Services.HypergridService //public InventoryCollection GetFolderContent(UUID principalID, UUID folderID) //{ //} - + + // NOGO + // + public override InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderID) + { + return new InventoryCollection[0]; + } + //public List GetFolderItems(UUID principalID, UUID folderID) //{ //} @@ -300,7 +299,7 @@ namespace OpenSim.Services.HypergridService UserAccount user = m_Cache.GetUser(it.CreatorId); // Adjust the creator data - if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty)) + if (user != null && it != null && string.IsNullOrEmpty(it.CreatorData)) it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName; } return it; diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs index 784f136..40eb6d4 100644 --- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs @@ -54,7 +54,7 @@ namespace OpenSim.Services.HypergridService LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); - private string m_HomeURL; +// private string m_HomeURL; private IUserAccountService m_UserAccountService; private IAvatarService m_AvatarService; @@ -96,8 +96,8 @@ namespace OpenSim.Services.HypergridService if (m_AvatarService == null) throw new Exception(String.Format("Unable to create m_AvatarService from {0}", avatarDll)); - // Preferred - m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL); +// m_HomeURL = Util.GetConfigVarFromSections(config, "HomeURI", +// new string[] { "Startup", "Hypergrid", m_ConfigName }, String.Empty); // m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); } @@ -115,8 +115,14 @@ namespace OpenSim.Services.HypergridService { XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + if (suitcase == null) + { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no suitcase folder for user {0} when looking for inventory skeleton", principalID); + return null; + } + List tree = GetFolderTree(principalID, suitcase.folderID); - if (tree == null || (tree != null && tree.Count == 0)) + if (tree.Count == 0) return null; List folders = new List(); @@ -131,58 +137,13 @@ namespace OpenSim.Services.HypergridService return folders; } - public override InventoryCollection GetUserInventory(UUID userID) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Get Suitcase inventory for user {0}", userID); - InventoryCollection userInventory = new InventoryCollection(); - userInventory.UserID = userID; - userInventory.Folders = new List(); - userInventory.Items = new List(); - - XInventoryFolder suitcase = GetSuitcaseXFolder(userID); - - List tree = GetFolderTree(userID, suitcase.folderID); - if (tree == null || (tree != null && tree.Count == 0)) - { - SetAsNormalFolder(suitcase); - userInventory.Folders.Add(ConvertToOpenSim(suitcase)); - return userInventory; - } - - List items; - foreach (XInventoryFolder f in tree) - { - // Add the items of this subfolder - items = GetFolderItems(userID, f.folderID); - if (items != null && items.Count > 0) - { - userInventory.Items.AddRange(items); - } - - // Add the folder itself - userInventory.Folders.Add(ConvertToOpenSim(f)); - } - - items = GetFolderItems(userID, suitcase.folderID); - if (items != null && items.Count > 0) - { - userInventory.Items.AddRange(items); - } - - SetAsNormalFolder(suitcase); - userInventory.Folders.Add(ConvertToOpenSim(suitcase)); - - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetUserInventory for user {0} returning {1} folders and {2} items", - userID, userInventory.Folders.Count, userInventory.Items.Count); - return userInventory; - } - public override InventoryFolderBase GetRootFolder(UUID principalID) { m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID); // Let's find out the local root folder - XInventoryFolder root = GetRootXFolder(principalID); ; + XInventoryFolder root = GetRootXFolder(principalID); + if (root == null) { m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID); @@ -195,14 +156,15 @@ namespace OpenSim.Services.HypergridService if (suitcase == null) { m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder. Creating it...", principalID); - // make one, and let's add it to the user's inventory as a direct child of the root folder - // In the DB we tag it as type 100, but we use -1 (Unknown) outside - suitcase = CreateFolder(principalID, root.folderID, 100, "My Suitcase"); + // Create the My Suitcase folder under the user's root folder. + // In the DB we tag it as type 100, but we use type 8 (Folder) outside, as this affects the sort order. + suitcase = CreateFolder(principalID, root.folderID, (int)FolderType.Suitcase, InventoryFolderBase.SUITCASE_FOLDER_NAME); if (suitcase == null) + { m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to create suitcase folder"); - m_Database.StoreFolder(suitcase); + return null; + } - // Create System folders CreateSystemFolders(principalID, suitcase.folderID); } @@ -216,45 +178,51 @@ namespace OpenSim.Services.HypergridService m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Creating System folders under Suitcase..."); XInventoryFolder[] sysFolders = GetSystemFolders(principalID, rootID); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.Animation, "Animations"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Bodypart) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.Bodypart, "Body Parts"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CallingCard) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.CallingCard, "Calling Cards"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Clothing) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.Clothing, "Clothing"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Gesture) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.Gesture, "Gestures"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Landmark) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.Landmark, "Landmarks"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LostAndFoundFolder) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.LostAndFoundFolder, "Lost And Found"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Notecard) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.Notecard, "Notecards"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Object) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.Object, "Objects"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.SnapshotFolder) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.SnapshotFolder, "Photo Album"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LSLText) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.LSLText, "Scripts"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Sound) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.Sound, "Sounds"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Texture) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.Texture, "Textures"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.TrashFolder) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.TrashFolder, "Trash"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.FavoriteFolder) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.FavoriteFolder, "Favorites"); - if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CurrentOutfitFolder) return true; return false; })) - CreateFolder(principalID, rootID, (int)AssetType.CurrentOutfitFolder, "Current Outfit"); - + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Animation) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.Animation, "Animations"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.BodyPart) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.BodyPart, "Body Parts"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.CallingCard) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.CallingCard, "Calling Cards"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Clothing) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.Clothing, "Clothing"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.CurrentOutfit) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.CurrentOutfit, "Current Outfit"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Favorites) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.Favorites, "Favorites"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Gesture) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.Gesture, "Gestures"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Landmark) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.Landmark, "Landmarks"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.LostAndFound) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.LostAndFound, "Lost And Found"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Notecard) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.Notecard, "Notecards"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Object) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.Object, "Objects"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Snapshot) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.Snapshot, "Photo Album"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.LSLText) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.LSLText, "Scripts"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Sound) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.Sound, "Sounds"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Texture) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.Texture, "Textures"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Trash) return true; return false; })) + CreateFolder(principalID, rootID, (int)FolderType.Trash, "Trash"); } - public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) + public override InventoryFolderBase GetFolderForType(UUID principalID, FolderType type) { //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type); XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + + if (suitcase == null) + { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no suitcase folder for user {0} when looking for child type folder {1}", principalID, type); + return null; + } + XInventoryFolder[] folders = m_Database.GetFolders( new string[] { "agentID", "type", "parentFolderID" }, new string[] { principalID.ToString(), ((int)type).ToString(), suitcase.folderID.ToString() }); @@ -277,7 +245,10 @@ namespace OpenSim.Services.HypergridService InventoryCollection coll = null; if (!IsWithinSuitcaseTree(principalID, folderID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderContent: folder {0} (user {1}) is not within Suitcase tree", folderID, principalID); return new InventoryCollection(); + } coll = base.GetFolderContent(principalID, folderID); @@ -294,7 +265,10 @@ namespace OpenSim.Services.HypergridService // Let's do a bit of sanity checking, more than the base service does // make sure the given folder exists under the suitcase tree of this user if (!IsWithinSuitcaseTree(principalID, folderID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderItems: folder {0} (user {1}) is not within Suitcase tree", folderID, principalID); return new List(); + } return base.GetFolderItems(principalID, folderID); } @@ -306,7 +280,10 @@ namespace OpenSim.Services.HypergridService // make sure the given folder's parent folder exists under the suitcase tree of this user if (!IsWithinSuitcaseTree(folder.Owner, folder.ParentID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder: folder {0} (user {1}) is not within Suitcase tree", folder.ParentID, folder.Owner); return false; + } // OK, it's legit if (base.AddFolder(folder)) @@ -326,7 +303,7 @@ namespace OpenSim.Services.HypergridService //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); if (!IsWithinSuitcaseTree(folder.Owner, folder.ID)) { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: UpdateFolder: folder {0}/{1} (user {2}) is not within Suitcase tree", folder.Name, folder.ID, folder.Owner); return false; } @@ -336,9 +313,17 @@ namespace OpenSim.Services.HypergridService public override bool MoveFolder(InventoryFolderBase folder) { - if (!IsWithinSuitcaseTree(folder.Owner, folder.ID) || - !IsWithinSuitcaseTree(folder.Owner, folder.ParentID)) + if (!IsWithinSuitcaseTree(folder.Owner, folder.ID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveFolder: folder {0} (user {1}) is not within Suitcase tree", folder.ID, folder.Owner); + return false; + } + + if (!IsWithinSuitcaseTree(folder.Owner, folder.ParentID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveFolder: folder {0} (user {1}) is not within Suitcase tree", folder.ParentID, folder.Owner); return false; + } return base.MoveFolder(folder); } @@ -360,7 +345,10 @@ namespace OpenSim.Services.HypergridService // Let's do a bit of sanity checking, more than the base service does // make sure the given folder's parent folder exists under the suitcase tree of this user if (!IsWithinSuitcaseTree(item.Owner, item.Folder)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddItem: folder {0} (user {1}) is not within Suitcase tree", item.Folder, item.Owner); return false; + } // OK, it's legit return base.AddItem(item); @@ -370,7 +358,10 @@ namespace OpenSim.Services.HypergridService public override bool UpdateItem(InventoryItemBase item) { if (!IsWithinSuitcaseTree(item.Owner, item.Folder)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: UpdateItem: folder {0} (user {1}) is not within Suitcase tree", item.Folder, item.Owner); return false; + } return base.UpdateItem(item); } @@ -379,11 +370,28 @@ namespace OpenSim.Services.HypergridService { // Principal is b0rked. *sigh* - if (!IsWithinSuitcaseTree(items[0].Owner, items[0].Folder)) - return false; + // Check the items' destination folders + foreach (InventoryItemBase item in items) + { + if (!IsWithinSuitcaseTree(item.Owner, item.Folder)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveItems: folder {0} (user {1}) is not within Suitcase tree", item.Folder, item.Owner); + return false; + } + } - return base.MoveItems(principalID, items); + // Check the items' current folders + foreach (InventoryItemBase item in items) + { + InventoryItemBase originalItem = base.GetItem(item); + if (!IsWithinSuitcaseTree(originalItem.Owner, originalItem.Folder)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveItems: folder {0} (user {1}) is not within Suitcase tree", item.Folder, item.Owner); + return false; + } + } + return base.MoveItems(principalID, items); } public override bool DeleteItems(UUID principalID, List itemIDs) @@ -403,8 +411,8 @@ namespace OpenSim.Services.HypergridService if (!IsWithinSuitcaseTree(it.Owner, it.Folder) && !IsPartOfAppearance(it.Owner, it.ID)) { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase", - it.Name, it.Folder); + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetItem: item {0}/{1} (folder {2}) (user {3}) is not within Suitcase tree or Appearance", + it.Name, it.ID, it.Folder, it.Owner); return null; } @@ -425,7 +433,11 @@ namespace OpenSim.Services.HypergridService if (f != null) { if (!IsWithinSuitcaseTree(f.Owner, f.ID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolder: folder {0}/{1} (user {2}) is not within Suitcase tree", + f.Name, f.ID, f.Owner); return null; + } } return f; @@ -456,7 +468,7 @@ namespace OpenSim.Services.HypergridService { XInventoryFolder[] folders = m_Database.GetFolders( new string[] { "agentID", "folderName", "type" }, - new string[] { principalID.ToString(), "My Inventory", ((int)AssetType.RootFolder).ToString() }); + new string[] { principalID.ToString(), InventoryFolderBase.ROOT_FOLDER_NAME, ((int)FolderType.Root).ToString() }); if (folders != null && folders.Length > 0) return folders[0]; @@ -464,7 +476,7 @@ namespace OpenSim.Services.HypergridService // OK, so the RootFolder type didn't work. Let's look for any type with parent UUID.Zero. folders = m_Database.GetFolders( new string[] { "agentID", "folderName", "parentFolderID" }, - new string[] { principalID.ToString(), "My Inventory", UUID.Zero.ToString() }); + new string[] { principalID.ToString(), InventoryFolderBase.ROOT_FOLDER_NAME, UUID.Zero.ToString() }); if (folders != null && folders.Length > 0) return folders[0]; @@ -472,12 +484,28 @@ namespace OpenSim.Services.HypergridService return null; } + private XInventoryFolder GetCurrentOutfitXFolder(UUID userID) + { + XInventoryFolder root = GetRootXFolder(userID); + if (root == null) + return null; + + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "type", "parentFolderID" }, + new string[] { userID.ToString(), ((int)FolderType.CurrentOutfit).ToString(), root.folderID.ToString() }); + + if (folders.Length == 0) + return null; + + return folders[0]; + } + private XInventoryFolder GetSuitcaseXFolder(UUID principalID) { // Warp! Root folder for travelers XInventoryFolder[] folders = m_Database.GetFolders( new string[] { "agentID", "type" }, - new string[] { principalID.ToString(), "100" }); // This is a special folder type... + new string[] { principalID.ToString(), ((int)FolderType.Suitcase).ToString() }); if (folders != null && folders.Length > 0) return folders[0]; @@ -485,13 +513,13 @@ namespace OpenSim.Services.HypergridService // check to see if we have the old Suitcase folder folders = m_Database.GetFolders( new string[] { "agentID", "folderName", "parentFolderID" }, - new string[] { principalID.ToString(), "My Suitcase", UUID.Zero.ToString() }); + new string[] { principalID.ToString(), InventoryFolderBase.SUITCASE_FOLDER_NAME, UUID.Zero.ToString() }); if (folders != null && folders.Length > 0) { // Move it to under the root folder XInventoryFolder root = GetRootXFolder(principalID); folders[0].parentFolderID = root.folderID; - folders[0].type = 100; + folders[0].type = (int)FolderType.Suitcase; m_Database.StoreFolder(folders[0]); return folders[0]; } @@ -501,17 +529,18 @@ namespace OpenSim.Services.HypergridService private void SetAsNormalFolder(XInventoryFolder suitcase) { - suitcase.type = (short)AssetType.Folder; + //suitcase.type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; } private List GetFolderTree(UUID principalID, UUID folder) { - List t = null; + List t; if (m_SuitcaseTrees.TryGetValue(principalID, out t)) return t; + // Get the tree of the suitcase folder t = GetFolderTreeRecursive(folder); - m_SuitcaseTrees.AddOrUpdate(principalID, t, 5*60); // 5minutes + m_SuitcaseTrees.AddOrUpdate(principalID, t, 5*60); // 5 minutes return t; } @@ -522,8 +551,10 @@ namespace OpenSim.Services.HypergridService new string[] { "parentFolderID" }, new string[] { root.ToString() }); - if (folders == null || (folders != null && folders.Length == 0)) + if (folders == null || folders.Length == 0) + { return tree; // empty tree + } else { foreach (XInventoryFolder f in folders) @@ -546,6 +577,7 @@ namespace OpenSim.Services.HypergridService private bool IsWithinSuitcaseTree(UUID principalID, UUID folderID) { XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + if (suitcase == null) { m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder", principalID); @@ -555,14 +587,18 @@ namespace OpenSim.Services.HypergridService List tree = new List(); tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder tree.AddRange(GetFolderTree(principalID, suitcase.folderID)); + + // Also add the Current Outfit folder to the list of available folders + XInventoryFolder folder = GetCurrentOutfitXFolder(principalID); + if (folder != null) + tree.Add(folder); + XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl) { - if (fl.folderID == folderID) return true; - else return false; + return (fl.folderID == folderID); }); - if (f == null) return false; - else return true; + return (f != null); } #endregion diff --git a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs index 49f2176..9999237 100644 --- a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/HypergridService/UserAccountCache.cs b/OpenSim/Services/HypergridService/UserAccountCache.cs index 65f9dd5..fa7dd0b 100644 --- a/OpenSim/Services/HypergridService/UserAccountCache.cs +++ b/OpenSim/Services/HypergridService/UserAccountCache.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Reflection; @@ -95,6 +95,11 @@ namespace OpenSim.Services.HypergridService return null; } + public void InvalidateCache(UUID userID) + { + m_UUIDCache.Remove(userID); + } + public bool StoreUserAccount(UserAccount data) { return false; diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index a26a922..c65122a 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.Net; using System.Reflection; +using OpenSim.Data; using OpenSim.Framework; using OpenSim.Services.Connectors.Friends; using OpenSim.Services.Connectors.Hypergrid; @@ -50,14 +51,14 @@ namespace OpenSim.Services.HypergridService /// needs to do it for them. /// Once we have better clients, this shouldn't be needed. /// - public class UserAgentService : IUserAgentService + public class UserAgentService : UserAgentServiceBase, IUserAgentService { private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); // This will need to go into a DB table - static Dictionary m_TravelingAgents = new Dictionary(); + //static Dictionary m_Database = new Dictionary(); static bool m_Initialized = false; @@ -74,6 +75,7 @@ namespace OpenSim.Services.HypergridService protected static string m_GridName; protected static int m_LevelOutsideContacts; + protected static bool m_ShowDetails; protected static bool m_BypassClientVerification; @@ -86,6 +88,7 @@ namespace OpenSim.Services.HypergridService } public UserAgentService(IConfigSource config, IFriendsSimConnector friendsConnector) + : base(config) { // Let's set this always, because we don't know the sequence // of instantiations @@ -126,20 +129,30 @@ namespace OpenSim.Services.HypergridService m_UserAccountService = ServerUtils.LoadPlugin(userAccountService, args); m_LevelOutsideContacts = serverConfig.GetInt("LevelOutsideContacts", 0); + m_ShowDetails = serverConfig.GetBoolean("ShowUserDetailsInHGProfile", true); LoadTripPermissionsFromConfig(serverConfig, "ForeignTripsAllowed"); LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_TripsAllowedExceptions); LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_TripsDisallowedExceptions); - m_GridName = serverConfig.GetString("ExternalName", string.Empty); - if (m_GridName == string.Empty) + m_GridName = Util.GetConfigVarFromSections(config, "GatekeeperURI", + new string[] { "Startup", "Hypergrid", "UserAgentService" }, String.Empty); + if (string.IsNullOrEmpty(m_GridName)) // Legacy. Remove soon. { - serverConfig = config.Configs["GatekeeperService"]; m_GridName = serverConfig.GetString("ExternalName", string.Empty); + if (m_GridName == string.Empty) + { + serverConfig = config.Configs["GatekeeperService"]; + m_GridName = serverConfig.GetString("ExternalName", string.Empty); + } } + if (!m_GridName.EndsWith("/")) m_GridName = m_GridName + "/"; + // Finally some cleanup + m_Database.DeleteOld(); + } } @@ -204,10 +217,10 @@ namespace OpenSim.Services.HypergridService return home; } - public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason) + public bool LoginAgentToGrid(GridRegion source, AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason) { m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", - agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); + agentCircuit.firstname, agentCircuit.lastname, (fromLogin ? agentCircuit.IPAddress : "stored IP"), gatekeeper.ServerURI); string gridName = gatekeeper.ServerURI; @@ -254,21 +267,21 @@ namespace OpenSim.Services.HypergridService // Generate a new service session agentCircuit.ServiceSessionID = region.ServerURI + ";" + UUID.Random(); - TravelingAgentInfo old = UpdateTravelInfo(agentCircuit, region); + TravelingAgentInfo old = null; + TravelingAgentInfo travel = CreateTravelInfo(agentCircuit, region, fromLogin, out old); bool success = false; string myExternalIP = string.Empty; - m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); + m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}, desired region: {2}", m_GridName, gridName, region.RegionID); if (m_GridName == gridName) - success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); + { + success = m_GatekeeperService.LoginAgent(source, agentCircuit, finalDestination, out reason); + } else { - success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason); - if (success) - // Report them as nowhere - m_PresenceService.ReportAgent(agentCircuit.SessionID, UUID.Zero); + success = m_GatekeeperConnector.CreateAgent(source, region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason); } if (!success) @@ -276,84 +289,64 @@ namespace OpenSim.Services.HypergridService m_log.DebugFormat("[USER AGENT SERVICE]: Unable to login user {0} {1} to grid {2}, reason: {3}", agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason); - // restore the old travel info - lock (m_TravelingAgents) - { - if (old == null) - m_TravelingAgents.Remove(agentCircuit.SessionID); - else - m_TravelingAgents[agentCircuit.SessionID] = old; - } + if (old != null) + StoreTravelInfo(old); + else + m_Database.Delete(agentCircuit.SessionID); return false; } + // Everything is ok + + // Update the perceived IP Address of our grid m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP); - // else set the IP addresses associated with this client - if (clientIP != null) - m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); - m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; + travel.MyIpAddress = myExternalIP; + + StoreTravelInfo(travel); return true; } - public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason) + public bool LoginAgentToGrid(GridRegion source, AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason) { reason = string.Empty; - return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, null, out reason); + return LoginAgentToGrid(source, agentCircuit, gatekeeper, finalDestination, false, out reason); } - private void SetClientIP(UUID sessionID, string ip) + TravelingAgentInfo CreateTravelInfo(AgentCircuitData agentCircuit, GridRegion region, bool fromLogin, out TravelingAgentInfo existing) { - if (m_TravelingAgents.ContainsKey(sessionID)) - { - m_log.DebugFormat("[USER AGENT SERVICE]: Setting IP {0} for session {1}", ip, sessionID); - m_TravelingAgents[sessionID].ClientIPAddress = ip; - } - } + HGTravelingData hgt = m_Database.Get(agentCircuit.SessionID); + existing = null; - TravelingAgentInfo UpdateTravelInfo(AgentCircuitData agentCircuit, GridRegion region) - { - TravelingAgentInfo travel = new TravelingAgentInfo(); - TravelingAgentInfo old = null; - lock (m_TravelingAgents) + if (hgt != null) { - if (m_TravelingAgents.ContainsKey(agentCircuit.SessionID)) - { - // Very important! Override whatever this agent comes with. - // UserAgentService always sets the IP for every new agent - // with the original IP address. - agentCircuit.IPAddress = m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress; - - old = m_TravelingAgents[agentCircuit.SessionID]; - } - - m_TravelingAgents[agentCircuit.SessionID] = travel; + // Very important! Override whatever this agent comes with. + // UserAgentService always sets the IP for every new agent + // with the original IP address. + existing = new TravelingAgentInfo(hgt); + agentCircuit.IPAddress = existing.ClientIPAddress; } + + TravelingAgentInfo travel = new TravelingAgentInfo(existing); + travel.SessionID = agentCircuit.SessionID; travel.UserID = agentCircuit.AgentID; travel.GridExternalName = region.ServerURI; travel.ServiceToken = agentCircuit.ServiceSessionID; - if (old != null) - travel.ClientIPAddress = old.ClientIPAddress; - return old; + if (fromLogin) + travel.ClientIPAddress = agentCircuit.IPAddress; + + StoreTravelInfo(travel); + + return travel; } public void LogoutAgent(UUID userID, UUID sessionID) { m_log.DebugFormat("[USER AGENT SERVICE]: User {0} logged out", userID); - lock (m_TravelingAgents) - { - List travels = new List(); - foreach (KeyValuePair kvp in m_TravelingAgents) - if (kvp.Value == null) // do some clean up - travels.Add(kvp.Key); - else if (kvp.Value.UserID == userID) - travels.Add(kvp.Key); - foreach (UUID session in travels) - m_TravelingAgents.Remove(session); - } + m_Database.Delete(sessionID); GridUserInfo guinfo = m_GridUserService.GetGridUserInfo(userID.ToString()); if (guinfo != null) @@ -363,10 +356,11 @@ namespace OpenSim.Services.HypergridService // We need to prevent foreign users with the same UUID as a local user public bool IsAgentComingHome(UUID sessionID, string thisGridExternalName) { - if (!m_TravelingAgents.ContainsKey(sessionID)) + HGTravelingData hgt = m_Database.Get(sessionID); + if (hgt == null) return false; - TravelingAgentInfo travel = m_TravelingAgents[sessionID]; + TravelingAgentInfo travel = new TravelingAgentInfo(hgt); return travel.GridExternalName.ToLower() == thisGridExternalName.ToLower(); } @@ -379,31 +373,32 @@ namespace OpenSim.Services.HypergridService m_log.DebugFormat("[USER AGENT SERVICE]: Verifying Client session {0} with reported IP {1}.", sessionID, reportedIP); - if (m_TravelingAgents.ContainsKey(sessionID)) - { - bool result = m_TravelingAgents[sessionID].ClientIPAddress == reportedIP || - m_TravelingAgents[sessionID].MyIpAddress == reportedIP; // NATed + HGTravelingData hgt = m_Database.Get(sessionID); + if (hgt == null) + return false; - m_log.DebugFormat("[USER AGENT SERVICE]: Comparing {0} with login IP {1} and MyIP {1}; result is {3}", - reportedIP, m_TravelingAgents[sessionID].ClientIPAddress, m_TravelingAgents[sessionID].MyIpAddress, result); + TravelingAgentInfo travel = new TravelingAgentInfo(hgt); - return result; - } + bool result = travel.ClientIPAddress == reportedIP || travel.MyIpAddress == reportedIP; // NATed + + m_log.DebugFormat("[USER AGENT SERVICE]: Comparing {0} with login IP {1} and MyIP {1}; result is {3}", + reportedIP, travel.ClientIPAddress, travel.MyIpAddress, result); - return false; + return result; } public bool VerifyAgent(UUID sessionID, string token) { - if (m_TravelingAgents.ContainsKey(sessionID)) + HGTravelingData hgt = m_Database.Get(sessionID); + if (hgt == null) { - m_log.DebugFormat("[USER AGENT SERVICE]: Verifying agent token {0} against {1}", token, m_TravelingAgents[sessionID].ServiceToken); - return m_TravelingAgents[sessionID].ServiceToken == token; + m_log.DebugFormat("[USER AGENT SERVICE]: Token verification for session {0}: no such session", sessionID); + return false; } - m_log.DebugFormat("[USER AGENT SERVICE]: Token verification for session {0}: no such session", sessionID); - - return false; + TravelingAgentInfo travel = new TravelingAgentInfo(hgt); + m_log.DebugFormat("[USER AGENT SERVICE]: Verifying agent token {0} against {1}", token, travel.ServiceToken); + return travel.ServiceToken == token; } [Obsolete] @@ -466,17 +461,17 @@ namespace OpenSim.Services.HypergridService } } - // Lastly, let's notify the rest who may be online somewhere else - foreach (string user in usersToBeNotified) - { - UUID id = new UUID(user); - if (m_TravelingAgents.ContainsKey(id) && m_TravelingAgents[id].GridExternalName != m_GridName) - { - string url = m_TravelingAgents[id].GridExternalName; - // forward - m_log.WarnFormat("[USER AGENT SERVICE]: User {0} is visiting {1}. HG Status notifications still not implemented.", user, url); - } - } + //// Lastly, let's notify the rest who may be online somewhere else + //foreach (string user in usersToBeNotified) + //{ + // UUID id = new UUID(user); + // if (m_Database.ContainsKey(id) && m_Database[id].GridExternalName != m_GridName) + // { + // string url = m_Database[id].GridExternalName; + // // forward + // m_log.WarnFormat("[USER AGENT SERVICE]: User {0} is visiting {1}. HG Status notifications still not implemented.", user, url); + // } + //} // and finally, let's send the online friends if (online) @@ -578,10 +573,22 @@ namespace OpenSim.Services.HypergridService if (account != null) { - info.Add("user_flags", (object)account.UserFlags); - info.Add("user_created", (object)account.Created); - info.Add("user_title", (object)account.UserTitle); + info.Add("user_firstname", account.FirstName); + info.Add("user_lastname", account.LastName); info.Add("result", "success"); + + if (m_ShowDetails) + { + info.Add("user_flags", account.UserFlags); + info.Add("user_created", account.Created); + info.Add("user_title", account.UserTitle); + } + else + { + info.Add("user_flags", 0); + info.Add("user_created", 0); + info.Add("user_title", string.Empty); + } } return info; @@ -603,16 +610,13 @@ namespace OpenSim.Services.HypergridService public string LocateUser(UUID userID) { - foreach (TravelingAgentInfo t in m_TravelingAgents.Values) - { - if (t == null) - { - m_log.ErrorFormat("[USER AGENT SERVICE]: Oops! Null TravelingAgentInfo. Please report this on mantis"); - continue; - } - if (t.UserID == userID && !m_GridName.Equals(t.GridExternalName)) - return t.GridExternalName; - } + HGTravelingData[] hgts = m_Database.GetSessions(userID); + if (hgts == null) + return string.Empty; + + foreach (HGTravelingData t in hgts) + if (t.Data.ContainsKey("GridExternalName") && !m_GridName.Equals(t.Data["GridExternalName"])) + return t.Data["GridExternalName"]; return string.Empty; } @@ -683,17 +687,60 @@ namespace OpenSim.Services.HypergridService return exception; } + private void StoreTravelInfo(TravelingAgentInfo travel) + { + if (travel == null) + return; + + HGTravelingData hgt = new HGTravelingData(); + hgt.SessionID = travel.SessionID; + hgt.UserID = travel.UserID; + hgt.Data = new Dictionary(); + hgt.Data["GridExternalName"] = travel.GridExternalName; + hgt.Data["ServiceToken"] = travel.ServiceToken; + hgt.Data["ClientIPAddress"] = travel.ClientIPAddress; + hgt.Data["MyIPAddress"] = travel.MyIpAddress; + + m_Database.Store(hgt); + } #endregion } class TravelingAgentInfo { + public UUID SessionID; public UUID UserID; public string GridExternalName = string.Empty; public string ServiceToken = string.Empty; public string ClientIPAddress = string.Empty; // as seen from this user agent service public string MyIpAddress = string.Empty; // the user agent service's external IP, as seen from the next gatekeeper + + public TravelingAgentInfo(HGTravelingData t) + { + if (t.Data != null) + { + SessionID = new UUID(t.SessionID); + UserID = new UUID(t.UserID); + GridExternalName = t.Data["GridExternalName"]; + ServiceToken = t.Data["ServiceToken"]; + ClientIPAddress = t.Data["ClientIPAddress"]; + MyIpAddress = t.Data["MyIPAddress"]; + } + } + + public TravelingAgentInfo(TravelingAgentInfo old) + { + if (old != null) + { + SessionID = old.SessionID; + UserID = old.UserID; + GridExternalName = old.GridExternalName; + ServiceToken = old.ServiceToken; + ClientIPAddress = old.ClientIPAddress; + MyIpAddress = old.MyIpAddress; + } + } } } diff --git a/OpenSim/Services/HypergridService/UserAgentServiceBase.cs b/OpenSim/Services/HypergridService/UserAgentServiceBase.cs new file mode 100644 index 0000000..a00e5a6 --- /dev/null +++ b/OpenSim/Services/HypergridService/UserAgentServiceBase.cs @@ -0,0 +1,84 @@ +/* + * 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 OpenSimulator 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.Reflection; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Data; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Base; + +namespace OpenSim.Services.HypergridService +{ + public class UserAgentServiceBase : ServiceBase + { + protected IHGTravelingData m_Database = null; + + public UserAgentServiceBase(IConfigSource config) + : base(config) + { + string dllName = String.Empty; + string connString = String.Empty; + string realm = "hg_traveling_data"; + + // + // Try reading the [DatabaseService] section, if it exists + // + IConfig dbConfig = config.Configs["DatabaseService"]; + if (dbConfig != null) + { + if (dllName == String.Empty) + dllName = dbConfig.GetString("StorageProvider", String.Empty); + if (connString == String.Empty) + connString = dbConfig.GetString("ConnectionString", String.Empty); + } + + // + // [UserAgentService] section overrides [DatabaseService], if it exists + // + IConfig gridConfig = config.Configs["UserAgentService"]; + if (gridConfig != null) + { + dllName = gridConfig.GetString("StorageProvider", dllName); + connString = gridConfig.GetString("ConnectionString", connString); + realm = gridConfig.GetString("Realm", realm); + } + + // + // We tried, but this doesn't exist. We can't proceed. + // + if (dllName.Equals(String.Empty)) + throw new Exception("No StorageProvider configured"); + + m_Database = LoadPlugin(dllName, new Object[] { connString, realm }); + if (m_Database == null) + throw new Exception("Could not find a storage interface in the given module"); + + } + } +} diff --git a/OpenSim/Services/Interfaces/IAgentPreferencesService.cs b/OpenSim/Services/Interfaces/IAgentPreferencesService.cs new file mode 100644 index 0000000..3b4fda2 --- /dev/null +++ b/OpenSim/Services/Interfaces/IAgentPreferencesService.cs @@ -0,0 +1,115 @@ +/* + * 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 OpenSimulator 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.Generic; +using OpenMetaverse; + +namespace OpenSim.Services.Interfaces +{ + public class AgentPrefs + { + public AgentPrefs(UUID principalID) + { + PrincipalID = principalID; + } + + public AgentPrefs(Dictionary kvp) + { + if (kvp.ContainsKey("PrincipalID")) + UUID.TryParse(kvp["PrincipalID"], out PrincipalID); + if (kvp.ContainsKey("AccessPrefs")) + AccessPrefs = kvp["AccessPrefs"]; + if (kvp.ContainsKey("HoverHeight")) + HoverHeight = double.Parse(kvp["HoverHeight"]); + if (kvp.ContainsKey("Language")) + Language = kvp["Language"]; + if (kvp.ContainsKey("LanguageIsPublic")) + LanguageIsPublic = bool.Parse(kvp["LanguageIsPublic"]); + if (kvp.ContainsKey("PermEveryone")) + PermEveryone = int.Parse(kvp["PermEveryone"]); + if (kvp.ContainsKey("PermGroup")) + PermGroup = int.Parse(kvp["PermGroup"]); + if (kvp.ContainsKey("PermNextOwner")) + PermNextOwner = int.Parse(kvp["PermNextOwner"]); + } + + public AgentPrefs(Dictionary kvp) + { + if (kvp.ContainsKey("PrincipalID")) + UUID.TryParse(kvp["PrincipalID"].ToString(), out PrincipalID); + if (kvp.ContainsKey("AccessPrefs")) + AccessPrefs = kvp["AccessPrefs"].ToString(); + if (kvp.ContainsKey("HoverHeight")) + HoverHeight = double.Parse(kvp["HoverHeight"].ToString()); + if (kvp.ContainsKey("Language")) + Language = kvp["Language"].ToString(); + if (kvp.ContainsKey("LanguageIsPublic")) + LanguageIsPublic = bool.Parse(kvp["LanguageIsPublic"].ToString()); + if (kvp.ContainsKey("PermEveryone")) + PermEveryone = int.Parse(kvp["PermEveryone"].ToString()); + if (kvp.ContainsKey("PermGroup")) + PermGroup = int.Parse(kvp["PermGroup"].ToString()); + if (kvp.ContainsKey("PermNextOwner")) + PermNextOwner = int.Parse(kvp["PermNextOwner"].ToString()); + } + + public Dictionary ToKeyValuePairs() + { + Dictionary result = new Dictionary(); + result["PrincipalID"] = PrincipalID.ToString(); + result["AccessPrefs"] = AccessPrefs.ToString(); + result["HoverHeight"] = HoverHeight.ToString(); + result["Language"] = Language.ToString(); + result["LanguageIsPublic"] = LanguageIsPublic.ToString(); + result["PermEveryone"] = PermEveryone.ToString(); + result["PermGroup"] = PermGroup.ToString(); + result["PermNextOwner"] = PermNextOwner.ToString(); + return result; + } + + public UUID PrincipalID = UUID.Zero; + public string AccessPrefs = "M"; + //public int GodLevel; // *TODO: Implement GodLevel (Unused by the viewer, afaict - 6/11/2015) + public double HoverHeight = 0.0; + public string Language = "en-us"; + public bool LanguageIsPublic = true; + // DefaultObjectPermMasks + public int PermEveryone = 0; + public int PermGroup = 0; + public int PermNextOwner = 532480; + } + + public interface IAgentPreferencesService + { + AgentPrefs GetAgentPreferences(UUID principalID); + bool StoreAgentPreferences(AgentPrefs data); + + string GetLang(UUID principalID); + } +} + diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs index 3c469c6..28c3315 100644 --- a/OpenSim/Services/Interfaces/IAssetService.cs +++ b/OpenSim/Services/Interfaces/IAssetService.cs @@ -75,6 +75,13 @@ namespace OpenSim.Services.Interfaces /// /// True if the id was parseable, false otherwise bool Get(string id, Object sender, AssetRetrieved handler); + + /// + /// Check if assets exist in the database. + /// + /// The assets' IDs + /// For each asset: true if it exists, false otherwise + bool[] AssetsExist(string[] ids); /// /// Creates a new asset @@ -83,7 +90,7 @@ namespace OpenSim.Services.Interfaces /// Returns a random ID if none is passed via the asset argument. /// /// - /// + /// The Asset ID, or string.Empty if an error occurred string Store(AssetBase asset); /// diff --git a/OpenSim/Services/Interfaces/IAvatarService.cs b/OpenSim/Services/Interfaces/IAvatarService.cs index 863fd93..892e0b4 100644 --- a/OpenSim/Services/Interfaces/IAvatarService.cs +++ b/OpenSim/Services/Interfaces/IAvatarService.cs @@ -162,10 +162,15 @@ namespace OpenSim.Services.Interfaces } // Visual Params - string[] vps = new string[AvatarAppearance.VISUALPARAM_COUNT]; + //string[] vps = new string[AvatarAppearance.VISUALPARAM_COUNT]; + //byte[] binary = appearance.VisualParams; + + // for (int i = 0 ; i < AvatarAppearance.VISUALPARAM_COUNT ; i++) + byte[] binary = appearance.VisualParams; + string[] vps = new string[binary.Length]; - for (int i = 0 ; i < AvatarAppearance.VISUALPARAM_COUNT ; i++) + for (int i = 0; i < binary.Length; i++) { vps[i] = binary[i].ToString(); } @@ -174,11 +179,18 @@ namespace OpenSim.Services.Interfaces // Attachments List attachments = appearance.GetAttachments(); + Dictionary> atts = new Dictionary>(); foreach (AvatarAttachment attach in attachments) { if (attach.ItemID != UUID.Zero) - Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString(); + { + if (!atts.ContainsKey(attach.AttachPoint)) + atts[attach.AttachPoint] = new List(); + atts[attach.AttachPoint].Add(attach.ItemID.ToString()); + } } + foreach (KeyValuePair> kvp in atts) + Data["_ap_" + kvp.Key] = string.Join(",", kvp.Value.ToArray()); } public AvatarAppearance ToAvatarAppearance() @@ -195,7 +207,13 @@ namespace OpenSim.Services.Interfaces appearance.Serial = Int32.Parse(Data["Serial"]); if (Data.ContainsKey("AvatarHeight")) - appearance.AvatarHeight = float.Parse(Data["AvatarHeight"]); + { + float h = float.Parse(Data["AvatarHeight"]); + if( h == 0f) + h = 1.9f; + + appearance.AvatarHeight = h; + } // Legacy Wearables if (Data.ContainsKey("BodyItem")) @@ -266,9 +284,13 @@ namespace OpenSim.Services.Interfaces if (Data.ContainsKey("VisualParams")) { string[] vps = Data["VisualParams"].Split(new char[] {','}); - byte[] binary = new byte[AvatarAppearance.VISUALPARAM_COUNT]; + //byte[] binary = new byte[AvatarAppearance.VISUALPARAM_COUNT]; - for (int i = 0 ; i < vps.Length && i < binary.Length ; i++) + //for (int i = 0 ; i < vps.Length && i < binary.Length ; i++) + + byte[] binary = new byte[vps.Length]; + + for (int i = 0; i < vps.Length; i++) binary[i] = (byte)Convert.ToInt32(vps[i]); appearance.VisualParams = binary; @@ -304,10 +326,16 @@ namespace OpenSim.Services.Interfaces if (!Int32.TryParse(pointStr, out point)) continue; - UUID uuid = UUID.Zero; - UUID.TryParse(_kvp.Value, out uuid); + List idList = new List(_kvp.Value.Split(new char[] {','})); - appearance.SetAttachment(point, uuid, UUID.Zero); + appearance.SetAttachment(point, UUID.Zero, UUID.Zero); + foreach (string id in idList) + { + UUID uuid = UUID.Zero; + UUID.TryParse(id, out uuid); + + appearance.SetAttachment(point | 0x80, uuid, UUID.Zero); + } } if (appearance.Wearables[AvatarWearable.BODY].Count == 0) diff --git a/OpenSim/Services/Interfaces/IBakedTextureService.cs b/OpenSim/Services/Interfaces/IBakedTextureService.cs new file mode 100644 index 0000000..69df4a0 --- /dev/null +++ b/OpenSim/Services/Interfaces/IBakedTextureService.cs @@ -0,0 +1,38 @@ +/* + * 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 OpenSimulator 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 Nini.Config; + +namespace OpenSim.Services.Interfaces +{ + public interface IBakedTextureService + { + string Get(string id); + void Store(string id, string data); + } +} diff --git a/OpenSim/Services/Interfaces/IBansService.cs b/OpenSim/Services/Interfaces/IBansService.cs new file mode 100644 index 0000000..8fd3521 --- /dev/null +++ b/OpenSim/Services/Interfaces/IBansService.cs @@ -0,0 +1,48 @@ +/* + * 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 OpenSimulator 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.Generic; + +using OpenSim.Framework; +using OpenMetaverse; + +namespace OpenSim.Services.Interfaces +{ + public interface IBansService + { + /// + /// Are any of the given arguments banned from the grid? + /// + /// + /// + /// + /// + /// + bool IsBanned(string userID, string ip, string id0, string origin); + } + +} diff --git a/OpenSim/Services/Interfaces/IEstateDataService.cs b/OpenSim/Services/Interfaces/IEstateDataService.cs new file mode 100644 index 0000000..719563d --- /dev/null +++ b/OpenSim/Services/Interfaces/IEstateDataService.cs @@ -0,0 +1,115 @@ +/* + * 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 OpenSimulator 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.Generic; +using OpenSim.Framework; +using OpenMetaverse; + +namespace OpenSim.Services.Interfaces +{ + public interface IEstateDataService + { + /// + /// Load estate settings for a region. + /// + /// + /// If true, then an estate is created if one is not found. + /// + EstateSettings LoadEstateSettings(UUID regionID, bool create); + + /// + /// Load estate settings for an estate ID. + /// + /// + /// + EstateSettings LoadEstateSettings(int estateID); + + /// + /// Create a new estate. + /// + /// + /// A + /// + EstateSettings CreateNewEstate(); + + /// + /// Load/Get all estate settings. + /// + /// An empty list if no estates were found. + List LoadEstateSettingsAll(); + + /// + /// Store estate settings. + /// + /// + /// This is also called by EstateSettings.Save() + /// + void StoreEstateSettings(EstateSettings es); + + /// + /// Get estate IDs. + /// + /// Name of estate to search for. This is the exact name, no parttern matching is done. + /// + List GetEstates(string search); + + /// + /// Get the IDs of all estates owned by the given user. + /// + /// An empty list if no estates were found. + List GetEstatesByOwner(UUID ownerID); + + /// + /// Get the IDs of all estates. + /// + /// An empty list if no estates were found. + List GetEstatesAll(); + + /// + /// Link a region to an estate. + /// + /// + /// + /// true if the link succeeded, false otherwise + bool LinkRegion(UUID regionID, int estateID); + + /// + /// Get the UUIDs of all the regions in an estate. + /// + /// + /// + List GetRegions(int estateID); + + /// + /// Delete an estate + /// + /// + /// true if the delete succeeded, false otherwise + bool DeleteEstate(int estateID); + } +} \ No newline at end of file diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index d7da056..f5f1f75 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -26,12 +26,17 @@ */ using System; +using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Sockets; +using System.Reflection; + using OpenSim.Framework; using OpenMetaverse; +using log4net; + namespace OpenSim.Services.Interfaces { public interface IGridService @@ -97,6 +102,7 @@ namespace OpenSim.Services.Interfaces List GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax); List GetDefaultRegions(UUID scopeID); + List GetDefaultHypergridRegions(UUID scopeID); List GetFallbackRegions(UUID scopeID, int x, int y); List GetHyperlinks(UUID scopeID); @@ -114,19 +120,28 @@ namespace OpenSim.Services.Interfaces /// /// int GetRegionFlags(UUID scopeID, UUID regionID); + + Dictionary GetExtraFeatures(); + } + + public interface IHypergridLinker + { + GridRegion TryLinkRegionToCoords(UUID scopeID, string mapName, int xloc, int yloc, UUID ownerID, out string reason); + bool TryUnlinkRegion(string mapName); } public class GridRegion { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + +#pragma warning disable 414 + private static readonly string LogHeader = "[GRID REGION]"; +#pragma warning restore 414 + /// /// The port by which http communication occurs with the region /// - public uint HttpPort - { - get { return m_httpPort; } - set { m_httpPort = value; } - } - protected uint m_httpPort; + public uint HttpPort { get; set; } /// /// A well-formed URI for the host region server (namely "http://" + ExternalHostName) @@ -134,14 +149,17 @@ namespace OpenSim.Services.Interfaces public string ServerURI { get { - if ( m_serverURI != string.Empty ) { + if (!String.IsNullOrEmpty(m_serverURI)) { return m_serverURI; } else { - return "http://" + m_externalHostName + ":" + m_httpPort + "/"; + if (HttpPort == 0) + return "http://" + m_externalHostName + "/"; + else + return "http://" + m_externalHostName + ":" + HttpPort + "/"; } } set { - if ( value.EndsWith("/") ) { + if (value.EndsWith("/")) { m_serverURI = value; } else { m_serverURI = value + '/'; @@ -150,6 +168,16 @@ namespace OpenSim.Services.Interfaces } protected string m_serverURI; + /// + /// Provides direct access to the 'm_serverURI' field, without returning a generated URL if m_serverURI is missing. + /// + public string RawServerURI + { + get { return m_serverURI; } + set { m_serverURI = value; } + } + + public string RegionName { get { return m_regionName; } @@ -157,22 +185,34 @@ namespace OpenSim.Services.Interfaces } protected string m_regionName = String.Empty; + /// + /// Region flags. + /// + /// + /// If not set (chiefly if a robust service is running code pre OpenSim 0.8.1) then this will be null and + /// should be ignored. If you require flags information please use the separate IGridService.GetRegionFlags() call + /// XXX: This field is currently ignored when used in RegisterRegion, but could potentially be + /// used to set flags at this point. + /// + public OpenSim.Framework.RegionFlags? RegionFlags { get; set; } + protected string m_externalHostName; protected IPEndPoint m_internalEndPoint; /// - /// The co-ordinate of this region. + /// The co-ordinate of this region in region units. /// - public int RegionCoordX { get { return RegionLocX / (int)Constants.RegionSize; } } + public int RegionCoordX { get { return (int)Util.WorldToRegionLoc((uint)RegionLocX); } } /// - /// The co-ordinate of this region + /// The co-ordinate of this region in region units /// - public int RegionCoordY { get { return RegionLocY / (int)Constants.RegionSize; } } + public int RegionCoordY { get { return (int)Util.WorldToRegionLoc((uint)RegionLocY); } } /// /// The location of this region in meters. + /// DANGER DANGER! Note that this name means something different in RegionInfo. /// public int RegionLocX { @@ -181,8 +221,12 @@ namespace OpenSim.Services.Interfaces } protected int m_regionLocX; + public int RegionSizeX { get; set; } + public int RegionSizeY { get; set; } + /// /// The location of this region in meters. + /// DANGER DANGER! Note that this name means something different in RegionInfo. /// public int RegionLocY { @@ -211,13 +255,18 @@ namespace OpenSim.Services.Interfaces public GridRegion() { + RegionSizeX = (int)Constants.RegionSize; + RegionSizeY = (int)Constants.RegionSize; m_serverURI = string.Empty; } + /* public GridRegion(int regionLocX, int regionLocY, IPEndPoint internalEndPoint, string externalUri) { m_regionLocX = regionLocX; m_regionLocY = regionLocY; + RegionSizeX = (int)Constants.RegionSize; + RegionSizeY = (int)Constants.RegionSize; m_internalEndPoint = internalEndPoint; m_externalHostName = externalUri; @@ -227,26 +276,33 @@ namespace OpenSim.Services.Interfaces { m_regionLocX = regionLocX; m_regionLocY = regionLocY; + RegionSizeX = (int)Constants.RegionSize; + RegionSizeY = (int)Constants.RegionSize; m_externalHostName = externalUri; m_internalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int)port); } + */ public GridRegion(uint xcell, uint ycell) { - m_regionLocX = (int)(xcell * Constants.RegionSize); - m_regionLocY = (int)(ycell * Constants.RegionSize); + m_regionLocX = (int)Util.RegionToWorldLoc(xcell); + m_regionLocY = (int)Util.RegionToWorldLoc(ycell); + RegionSizeX = (int)Constants.RegionSize; + RegionSizeY = (int)Constants.RegionSize; } public GridRegion(RegionInfo ConvertFrom) { m_regionName = ConvertFrom.RegionName; - m_regionLocX = (int)(ConvertFrom.RegionLocX * Constants.RegionSize); - m_regionLocY = (int)(ConvertFrom.RegionLocY * Constants.RegionSize); + m_regionLocX = (int)(ConvertFrom.WorldLocX); + m_regionLocY = (int)(ConvertFrom.WorldLocY); + RegionSizeX = (int)ConvertFrom.RegionSizeX; + RegionSizeY = (int)ConvertFrom.RegionSizeY; m_internalEndPoint = ConvertFrom.InternalEndPoint; m_externalHostName = ConvertFrom.ExternalHostName; - m_httpPort = ConvertFrom.HttpPort; + HttpPort = ConvertFrom.HttpPort; RegionID = ConvertFrom.RegionID; ServerURI = ConvertFrom.ServerURI; TerrainImage = ConvertFrom.RegionSettings.TerrainImageID; @@ -260,11 +316,14 @@ namespace OpenSim.Services.Interfaces public GridRegion(GridRegion ConvertFrom) { m_regionName = ConvertFrom.RegionName; + RegionFlags = ConvertFrom.RegionFlags; m_regionLocX = ConvertFrom.RegionLocX; m_regionLocY = ConvertFrom.RegionLocY; + RegionSizeX = ConvertFrom.RegionSizeX; + RegionSizeY = ConvertFrom.RegionSizeY; m_internalEndPoint = ConvertFrom.InternalEndPoint; m_externalHostName = ConvertFrom.ExternalHostName; - m_httpPort = ConvertFrom.HttpPort; + HttpPort = ConvertFrom.HttpPort; RegionID = ConvertFrom.RegionID; ServerURI = ConvertFrom.ServerURI; TerrainImage = ConvertFrom.TerrainImage; @@ -274,8 +333,112 @@ namespace OpenSim.Services.Interfaces RegionSecret = ConvertFrom.RegionSecret; EstateOwner = ConvertFrom.EstateOwner; } + + public GridRegion(Dictionary kvp) + { + if (kvp.ContainsKey("uuid")) + RegionID = new UUID((string)kvp["uuid"]); + + if (kvp.ContainsKey("locX")) + RegionLocX = Convert.ToInt32((string)kvp["locX"]); + + if (kvp.ContainsKey("locY")) + RegionLocY = Convert.ToInt32((string)kvp["locY"]); + + if (kvp.ContainsKey("sizeX")) + RegionSizeX = Convert.ToInt32((string)kvp["sizeX"]); + else + RegionSizeX = (int)Constants.RegionSize; + + if (kvp.ContainsKey("sizeY")) + RegionSizeY = Convert.ToInt32((string)kvp["sizeY"]); + else + RegionSizeX = (int)Constants.RegionSize; + + if (kvp.ContainsKey("regionName")) + RegionName = (string)kvp["regionName"]; + + if (kvp.ContainsKey("flags") && kvp["flags"] != null) + RegionFlags = (OpenSim.Framework.RegionFlags?)Convert.ToInt32((string)kvp["flags"]); + + if (kvp.ContainsKey("serverIP")) + { + //int port = 0; + //Int32.TryParse((string)kvp["serverPort"], out port); + //IPEndPoint ep = new IPEndPoint(IPAddress.Parse((string)kvp["serverIP"]), port); + ExternalHostName = (string)kvp["serverIP"]; + } + else + ExternalHostName = "127.0.0.1"; + + if (kvp.ContainsKey("serverPort")) + { + Int32 port = 0; + Int32.TryParse((string)kvp["serverPort"], out port); + InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), port); + } + + if (kvp.ContainsKey("serverHttpPort")) + { + UInt32 port = 0; + UInt32.TryParse((string)kvp["serverHttpPort"], out port); + HttpPort = port; + } + + if (kvp.ContainsKey("serverURI")) + ServerURI = (string)kvp["serverURI"]; + + if (kvp.ContainsKey("regionMapTexture")) + UUID.TryParse((string)kvp["regionMapTexture"], out TerrainImage); + + if (kvp.ContainsKey("parcelMapTexture")) + UUID.TryParse((string)kvp["parcelMapTexture"], out ParcelImage); + + if (kvp.ContainsKey("access")) + Access = Byte.Parse((string)kvp["access"]); + + if (kvp.ContainsKey("regionSecret")) + RegionSecret =(string)kvp["regionSecret"]; + + if (kvp.ContainsKey("owner_uuid")) + EstateOwner = new UUID(kvp["owner_uuid"].ToString()); + + if (kvp.ContainsKey("Token")) + Token = kvp["Token"].ToString(); + + // m_log.DebugFormat("{0} New GridRegion. id={1}, loc=<{2},{3}>, size=<{4},{5}>", + // LogHeader, RegionID, RegionLocX, RegionLocY, RegionSizeX, RegionSizeY); + } + + public Dictionary ToKeyValuePairs() + { + Dictionary kvp = new Dictionary(); + kvp["uuid"] = RegionID.ToString(); + kvp["locX"] = RegionLocX.ToString(); + kvp["locY"] = RegionLocY.ToString(); + kvp["sizeX"] = RegionSizeX.ToString(); + kvp["sizeY"] = RegionSizeY.ToString(); + kvp["regionName"] = RegionName; - # region Definition of equality + if (RegionFlags != null) + kvp["flags"] = ((int)RegionFlags).ToString(); + + kvp["serverIP"] = ExternalHostName; //ExternalEndPoint.Address.ToString(); + kvp["serverHttpPort"] = HttpPort.ToString(); + kvp["serverURI"] = ServerURI; + kvp["serverPort"] = InternalEndPoint.Port.ToString(); + kvp["regionMapTexture"] = TerrainImage.ToString(); + kvp["parcelMapTexture"] = ParcelImage.ToString(); + kvp["access"] = Access.ToString(); + kvp["regionSecret"] = RegionSecret; + kvp["owner_uuid"] = EstateOwner.ToString(); + kvp["Token"] = Token.ToString(); + // Maturity doesn't seem to exist in the DB + + return kvp; + } + + #region Definition of equality /// /// Define equality as two regions having the same, non-zero UUID. @@ -362,86 +525,5 @@ namespace OpenSim.Services.Interfaces { get { return Util.UIntsToLong((uint)RegionLocX, (uint)RegionLocY); } } - - public Dictionary ToKeyValuePairs() - { - Dictionary kvp = new Dictionary(); - kvp["uuid"] = RegionID.ToString(); - kvp["locX"] = RegionLocX.ToString(); - kvp["locY"] = RegionLocY.ToString(); - kvp["regionName"] = RegionName; - kvp["serverIP"] = ExternalHostName; //ExternalEndPoint.Address.ToString(); - kvp["serverHttpPort"] = HttpPort.ToString(); - kvp["serverURI"] = ServerURI; - kvp["serverPort"] = InternalEndPoint.Port.ToString(); - kvp["regionMapTexture"] = TerrainImage.ToString(); - kvp["parcelMapTexture"] = ParcelImage.ToString(); - kvp["access"] = Access.ToString(); - kvp["regionSecret"] = RegionSecret; - kvp["owner_uuid"] = EstateOwner.ToString(); - kvp["Token"] = Token.ToString(); - // Maturity doesn't seem to exist in the DB - return kvp; - } - - public GridRegion(Dictionary kvp) - { - if (kvp.ContainsKey("uuid")) - RegionID = new UUID((string)kvp["uuid"]); - - if (kvp.ContainsKey("locX")) - RegionLocX = Convert.ToInt32((string)kvp["locX"]); - - if (kvp.ContainsKey("locY")) - RegionLocY = Convert.ToInt32((string)kvp["locY"]); - - if (kvp.ContainsKey("regionName")) - RegionName = (string)kvp["regionName"]; - - if (kvp.ContainsKey("serverIP")) - { - //int port = 0; - //Int32.TryParse((string)kvp["serverPort"], out port); - //IPEndPoint ep = new IPEndPoint(IPAddress.Parse((string)kvp["serverIP"]), port); - ExternalHostName = (string)kvp["serverIP"]; - } - else - ExternalHostName = "127.0.0.1"; - - if (kvp.ContainsKey("serverPort")) - { - Int32 port = 0; - Int32.TryParse((string)kvp["serverPort"], out port); - InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), port); - } - - if (kvp.ContainsKey("serverHttpPort")) - { - UInt32 port = 0; - UInt32.TryParse((string)kvp["serverHttpPort"], out port); - HttpPort = port; - } - - if (kvp.ContainsKey("serverURI")) - ServerURI = (string)kvp["serverURI"]; - - if (kvp.ContainsKey("regionMapTexture")) - UUID.TryParse((string)kvp["regionMapTexture"], out TerrainImage); - - if (kvp.ContainsKey("parcelMapTexture")) - UUID.TryParse((string)kvp["parcelMapTexture"], out ParcelImage); - - if (kvp.ContainsKey("access")) - Access = Byte.Parse((string)kvp["access"]); - - if (kvp.ContainsKey("regionSecret")) - RegionSecret =(string)kvp["regionSecret"]; - - if (kvp.ContainsKey("owner_uuid")) - EstateOwner = new UUID(kvp["owner_uuid"].ToString()); - - if (kvp.ContainsKey("Token")) - Token = kvp["Token"].ToString(); - } } -} +} \ No newline at end of file diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs index 3dc877a..5e012fb 100644 --- a/OpenSim/Services/Interfaces/IHypergridServices.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -37,31 +37,71 @@ namespace OpenSim.Services.Interfaces public interface IGatekeeperService { bool LinkRegion(string regionDescriptor, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason); - GridRegion GetHyperlinkRegion(UUID regionID); + + /// + /// Returns the region a Hypergrid visitor should enter. + /// + /// + /// Usually the returned region will be the requested region. But the grid can choose to + /// redirect the user to another region: e.g., a default gateway region. + /// + /// The region the visitor *wants* to enter + /// The visitor's User ID. Will be missing (UUID.Zero) in older OpenSims. + /// The visitor's Home URI. Will be missing (null) in older OpenSims. + /// [out] A message to show to the user (optional, may be null) + /// The region the visitor should enter, or null if no region can be found / is allowed + GridRegion GetHyperlinkRegion(UUID regionID, UUID agentID, string agentHomeURI, out string message); - bool LoginAgent(AgentCircuitData aCircuit, GridRegion destination, out string reason); + bool LoginAgent(GridRegion source, AgentCircuitData aCircuit, GridRegion destination, out string reason); } - /// - /// HG1.5 only - /// public interface IUserAgentService { - // called by login service only - bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason); - // called by simulators - bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason); + bool LoginAgentToGrid(GridRegion source, AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason); + void LogoutAgent(UUID userID, UUID sessionID); + + /// + /// Returns the home region of a remote user. + /// + /// On success: the user's home region. If the user doesn't exist: null. + /// Throws an exception if an error occurs (e.g., can't contact the server). GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); + + /// + /// Returns the Server URLs of a remote user. + /// + /// On success: the user's Server URLs. If the user doesn't exist: an empty dictionary. + /// Throws an exception if an error occurs (e.g., can't contact the server). Dictionary GetServerURLs(UUID userID); - Dictionary GetUserInfo(UUID userID); + /// + /// Returns the UserInfo of a remote user. + /// + /// On success: the user's UserInfo. If the user doesn't exist: an empty dictionary. + /// Throws an exception if an error occurs (e.g., can't contact the server). + Dictionary GetUserInfo(UUID userID); + + /// + /// Returns the current location of a remote user. + /// + /// On success: the user's Server URLs. If the user doesn't exist: "". + /// Throws an exception if an error occurs (e.g., can't contact the server). string LocateUser(UUID userID); - // Tries to get the universal user identifier for the targetUserId - // on behalf of the userID + + /// + /// Returns the Universal User Identifier for 'targetUserID' on behalf of 'userID'. + /// + /// On success: the user's UUI. If the user doesn't exist: "". + /// Throws an exception if an error occurs (e.g., can't contact the server). string GetUUI(UUID userID, UUID targetUserID); + /// + /// Returns the remote user that has the given name. + /// + /// On success: the user's UUID. If the user doesn't exist: UUID.Zero. + /// Throws an exception if an error occurs (e.g., can't contact the server). UUID GetUUID(String first, String last); // Returns the local friends online diff --git a/OpenSim/Services/Interfaces/IInventoryService.cs b/OpenSim/Services/Interfaces/IInventoryService.cs index a8bfe47..4289bba 100644 --- a/OpenSim/Services/Interfaces/IInventoryService.cs +++ b/OpenSim/Services/Interfaces/IInventoryService.cs @@ -55,23 +55,6 @@ namespace OpenSim.Services.Interfaces List GetInventorySkeleton(UUID userId); /// - /// Synchronous inventory fetch. - /// - /// - /// - [Obsolete] - InventoryCollection GetUserInventory(UUID userID); - - /// - /// Request the inventory for a user. This is an asynchronous operation that will call the callback when the - /// inventory has been received - /// - /// - /// - [Obsolete] - void GetUserInventory(UUID userID, InventoryReceiptCallback callback); - - /// /// Retrieve the root inventory folder for the given user. /// /// @@ -84,15 +67,23 @@ namespace OpenSim.Services.Interfaces /// /// /// - InventoryFolderBase GetFolderForType(UUID userID, AssetType type); + InventoryFolderBase GetFolderForType(UUID userID, FolderType type); /// /// Gets everything (folders and items) inside a folder /// /// /// - /// + /// Inventory content. null if the request failed. InventoryCollection GetFolderContent(UUID userID, UUID folderID); + + /// + /// Gets everything (folders and items) inside a folder + /// + /// + /// + /// Inventory content. + InventoryCollection[] GetMultipleFoldersContent(UUID userID, UUID[] folderIDs); /// /// Gets the items inside a folder @@ -173,6 +164,13 @@ namespace OpenSim.Services.Interfaces InventoryItemBase GetItem(InventoryItemBase item); /// + /// Get multiple items, given by their UUIDs + /// + /// + /// null if no item was found, otherwise the found item + InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] ids); + + /// /// Get a folder, given by its UUID /// /// diff --git a/OpenSim/Services/Interfaces/IMapImageService.cs b/OpenSim/Services/Interfaces/IMapImageService.cs index a7b2cf1..78daa5f 100644 --- a/OpenSim/Services/Interfaces/IMapImageService.cs +++ b/OpenSim/Services/Interfaces/IMapImageService.cs @@ -35,6 +35,7 @@ namespace OpenSim.Services.Interfaces { //List GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY); bool AddMapTile(int x, int y, byte[] imageData, out string reason); + bool RemoveMapTile(int x, int y, out string reason); byte[] GetMapTile(string fileName, out string format); } } diff --git a/OpenSim/Services/Interfaces/IOfflineIMService.cs b/OpenSim/Services/Interfaces/IOfflineIMService.cs index 2848967..588aaaf 100644 --- a/OpenSim/Services/Interfaces/IOfflineIMService.cs +++ b/OpenSim/Services/Interfaces/IOfflineIMService.cs @@ -35,7 +35,14 @@ namespace OpenSim.Services.Interfaces public interface IOfflineIMService { List GetMessages(UUID principalID); + bool StoreMessage(GridInstantMessage im, out string reason); + + /// + /// Delete messages to or from this user (or group). + /// + /// A user or group ID + void DeleteMessages(UUID userID); } public class OfflineIMDataUtils diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs index b10a85c..8a25509 100644 --- a/OpenSim/Services/Interfaces/ISimulationService.cs +++ b/OpenSim/Services/Interfaces/ISimulationService.cs @@ -26,6 +26,7 @@ */ using System; +using System.Collections.Generic; using OpenSim.Framework; using OpenMetaverse; @@ -33,6 +34,20 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Services.Interfaces { + public class EntityTransferContext + { + public EntityTransferContext() + { + InboundVersion = VersionInfo.SimulationServiceVersionAcceptedMax; + OutboundVersion = VersionInfo.SimulationServiceVersionSupportedMax; + VariableWearablesSupported = false; + } + + public float InboundVersion { get; set; } + public float OutboundVersion { get; set; } + public bool VariableWearablesSupported { get; set; } + } + public interface ISimulationService { /// @@ -53,11 +68,13 @@ namespace OpenSim.Services.Interfaces /// /// Ask the simulator hosting the destination to create an agent on that region. /// + /// The region that the user is coming from. Will be null if the user + /// logged-in directly, or arrived from a simulator that doesn't send this parameter. /// /// /// /// Reason message in the event of a failure. - bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason); + bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason); /// /// Full child agent update. @@ -75,9 +92,21 @@ namespace OpenSim.Services.Interfaces /// bool UpdateAgent(GridRegion destination, AgentPosition data); - bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent); - - bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason); + /// + /// Returns whether a propspective user is allowed to visit the region. + /// + /// Desired destination + /// The visitor's User ID + /// The visitor's Home URI. Will be missing (null) in older OpenSims. + /// True: via teleport; False: via cross (walking) + /// Position in the region + /// + /// Version that the requesting simulator is runing. If null then no version check is carried out. + /// + /// Version that the target simulator is running + /// [out] Optional error message + /// True: ok; False: not allowed + bool QueryAccess(GridRegion destination, UUID agentID, string agentHomeURI, bool viaTeleport, Vector3 position, List features, EntityTransferContext ctx, out string reason); /// /// Message from receiving region to departing region, telling it got contacted by the client. @@ -95,7 +124,7 @@ namespace OpenSim.Services.Interfaces /// /// /// - bool CloseAgent(GridRegion destination, UUID id); + bool CloseAgent(GridRegion destination, UUID id, string auth_token); #endregion Agents diff --git a/OpenSim/Services/Interfaces/IUserAccountService.cs b/OpenSim/Services/Interfaces/IUserAccountService.cs index 1b85980..2f7702c 100644 --- a/OpenSim/Services/Interfaces/IUserAccountService.cs +++ b/OpenSim/Services/Interfaces/IUserAccountService.cs @@ -189,5 +189,7 @@ namespace OpenSim.Services.Interfaces /// /// bool StoreUserAccount(UserAccount data); + + void InvalidateCache(UUID userID); } } diff --git a/OpenSim/Services/Interfaces/IUserManagement.cs b/OpenSim/Services/Interfaces/IUserManagement.cs new file mode 100644 index 0000000..9e560d5 --- /dev/null +++ b/OpenSim/Services/Interfaces/IUserManagement.cs @@ -0,0 +1,97 @@ +/* + * 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 OpenSimulator 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.Generic; + +using OpenMetaverse; + +namespace OpenSim.Services.Interfaces +{ + /// + /// This maintains the relationship between a UUID and a user name. + /// + public interface IUserManagement + { + string GetUserName(UUID uuid); + string GetUserHomeURL(UUID uuid); + string GetUserUUI(UUID uuid); + bool GetUserUUI(UUID userID, out string uui); + string GetUserServerURL(UUID uuid, string serverType); + + /// + /// Get user ID by the given name. + /// + /// + /// UUID.Zero if no user with that name is found or if the name is "Unknown User" + UUID GetUserIdByName(string name); + + /// + /// Get user ID by the given name. + /// + /// + /// + /// UUID.Zero if no user with that name is found or if the name is "Unknown User" + UUID GetUserIdByName(string firstName, string lastName); + + /// + /// Add a user. + /// + /// + /// If an account is found for the UUID, then the names in this will be used rather than any information + /// extracted from creatorData. + /// + /// + /// The creator data for this user. + void AddUser(UUID uuid, string creatorData); + + /// + /// Add a user. + /// + /// + /// The UUID is related to the name without any other checks being performed, such as user account presence. + /// + /// + /// + /// + void AddUser(UUID uuid, string firstName, string lastName); + + /// + /// Add a user. + /// + /// + /// The arguments apart from uuid are formed into a creatorData string and processing proceeds as for the + /// AddUser(UUID uuid, string creatorData) method. + /// + /// + /// + /// + void AddUser(UUID uuid, string firstName, string lastName, string homeURL); + + bool IsLocalGridUser(UUID uuid); + } +} diff --git a/OpenSim/Services/Interfaces/IUserProfilesService.cs b/OpenSim/Services/Interfaces/IUserProfilesService.cs new file mode 100644 index 0000000..121baa8 --- /dev/null +++ b/OpenSim/Services/Interfaces/IUserProfilesService.cs @@ -0,0 +1,80 @@ +/* + * 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 OpenSimulator 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 OpenSim.Framework; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Services.Interfaces +{ + public interface IUserProfilesService + { + #region Classifieds + OSD AvatarClassifiedsRequest(UUID creatorId); + bool ClassifiedUpdate(UserClassifiedAdd ad, ref string result); + bool ClassifiedInfoRequest(ref UserClassifiedAdd ad, ref string result); + bool ClassifiedDelete(UUID recordId); + #endregion Classifieds + + #region Picks + OSD AvatarPicksRequest(UUID creatorId); + bool PickInfoRequest(ref UserProfilePick pick, ref string result); + bool PicksUpdate(ref UserProfilePick pick, ref string result); + bool PicksDelete(UUID pickId); + #endregion Picks + + #region Notes + bool AvatarNotesRequest(ref UserProfileNotes note); + bool NotesUpdate(ref UserProfileNotes note, ref string result); + #endregion Notes + + #region Profile Properties + bool AvatarPropertiesRequest(ref UserProfileProperties prop, ref string result); + bool AvatarPropertiesUpdate(ref UserProfileProperties prop, ref string result); + #endregion Profile Properties + + #region User Preferences + bool UserPreferencesRequest(ref UserPreferences pref, ref string result); + bool UserPreferencesUpdate(ref UserPreferences pref, ref string result); + #endregion User Preferences + + #region Interests + bool AvatarInterestsUpdate(UserProfileProperties prop, ref string result); + #endregion Interests + + #region Utility + OSD AvatarImageAssetsRequest(UUID avatarId); + #endregion Utility + + #region UserData + bool RequestUserAppData(ref UserAppData prop, ref string result); + bool SetUserAppData(UserAppData prop, ref string result); + #endregion UserData + } +} + diff --git a/OpenSim/Services/Interfaces/OpenProfileClient.cs b/OpenSim/Services/Interfaces/OpenProfileClient.cs new file mode 100644 index 0000000..bda8151 --- /dev/null +++ b/OpenSim/Services/Interfaces/OpenProfileClient.cs @@ -0,0 +1,134 @@ +/* + * 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 OpenSimulator 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.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Text; +using System.Xml; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Services.UserProfilesService +{ + /// + /// A client for accessing a profile server using the OpenProfile protocol. + /// + /// + /// This class was adapted from the full OpenProfile class. Since it's only a client, and not a server, + /// it's much simpler. + /// + public class OpenProfileClient + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_serverURI; + + /// + /// Creates a client for accessing a foreign grid's profile server using the OpenProfile protocol. + /// + /// The grid's profile server URL + public OpenProfileClient(string serverURI) + { + m_serverURI = serverURI; + } + + /// + /// Gets an avatar's profile using the OpenProfile protocol. + /// + /// On success, this will contain the avatar's profile + /// Success/failure + /// + /// There are two profile modules currently in use in OpenSim: the older one is OpenProfile, and the newer + /// one is UserProfileModule (this file). This method attempts to read an avatar's profile from a foreign + /// grid using the OpenProfile protocol. + /// + public bool RequestAvatarPropertiesUsingOpenProfile(ref UserProfileProperties props) + { + Hashtable ReqHash = new Hashtable(); + ReqHash["avatar_id"] = props.UserId.ToString(); + + Hashtable profileData = XMLRPCRequester.SendRequest(ReqHash, "avatar_properties_request", m_serverURI); + + if (profileData == null) + return false; + if (!profileData.ContainsKey("data")) + return false; + + ArrayList dataArray = (ArrayList)profileData["data"]; + + if (dataArray == null || dataArray[0] == null) + return false; + profileData = (Hashtable)dataArray[0]; + + props.WebUrl = string.Empty; + props.AboutText = String.Empty; + props.FirstLifeText = String.Empty; + props.ImageId = UUID.Zero; + props.FirstLifeImageId = UUID.Zero; + props.PartnerId = UUID.Zero; + + if (profileData["ProfileUrl"] != null) + props.WebUrl = profileData["ProfileUrl"].ToString(); + if (profileData["AboutText"] != null) + props.AboutText = profileData["AboutText"].ToString(); + if (profileData["FirstLifeAboutText"] != null) + props.FirstLifeText = profileData["FirstLifeAboutText"].ToString(); + if (profileData["Image"] != null) + props.ImageId = new UUID(profileData["Image"].ToString()); + if (profileData["FirstLifeImage"] != null) + props.FirstLifeImageId = new UUID(profileData["FirstLifeImage"].ToString()); + if (profileData["Partner"] != null) + props.PartnerId = new UUID(profileData["Partner"].ToString()); + + props.WantToMask = 0; + props.WantToText = String.Empty; + props.SkillsMask = 0; + props.SkillsText = String.Empty; + props.Language = String.Empty; + + if (profileData["wantmask"] != null) + props.WantToMask = Convert.ToInt32(profileData["wantmask"].ToString()); + if (profileData["wanttext"] != null) + props.WantToText = profileData["wanttext"].ToString(); + + if (profileData["skillsmask"] != null) + props.SkillsMask = Convert.ToInt32(profileData["skillsmask"].ToString()); + if (profileData["skillstext"] != null) + props.SkillsText = profileData["skillstext"].ToString(); + + if (profileData["languages"] != null) + props.Language = profileData["languages"].ToString(); + + return true; + } + } +} \ No newline at end of file diff --git a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs index 4723553..01cafbf 100644 --- a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/InventoryService/LibraryService.cs b/OpenSim/Services/InventoryService/LibraryService.cs index f90895b..c4a5572 100644 --- a/OpenSim/Services/InventoryService/LibraryService.cs +++ b/OpenSim/Services/InventoryService/LibraryService.cs @@ -38,6 +38,7 @@ using OpenSim.Services.Interfaces; using log4net; using Nini.Config; using OpenMetaverse; +using PermissionMask = OpenSim.Framework.PermissionMask; namespace OpenSim.Services.InventoryService { diff --git a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs index 41ad9f8..ec89097 100644 --- a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 7bad4b0..b75193f 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -111,40 +111,48 @@ namespace OpenSim.Services.InventoryService if (rootFolder == null) { - rootFolder = ConvertToOpenSim(CreateFolder(principalID, UUID.Zero, (int)AssetType.RootFolder, "My Inventory")); + rootFolder = ConvertToOpenSim(CreateFolder(principalID, UUID.Zero, (int)FolderType.Root, InventoryFolderBase.ROOT_FOLDER_NAME)); result = true; } XInventoryFolder[] sysFolders = GetSystemFolders(principalID, rootFolder.ID); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.Animation, "Animations"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Bodypart) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.Bodypart, "Body Parts"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.CallingCard) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.CallingCard, "Calling Cards"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Clothing) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.Clothing, "Clothing"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Gesture) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.Gesture, "Gestures"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Landmark) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.Landmark, "Landmarks"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.LostAndFoundFolder) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.LostAndFoundFolder, "Lost And Found"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Notecard) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.Notecard, "Notecards"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Object) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.Object, "Objects"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.SnapshotFolder) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.SnapshotFolder, "Photo Album"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.LSLText) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.LSLText, "Scripts"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Sound) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.Sound, "Sounds"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Texture) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.Texture, "Textures"); - if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.TrashFolder) return true; return false; })) - CreateFolder(principalID, rootFolder.ID, (int)AssetType.TrashFolder, "Trash"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Animation) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.Animation, "Animations"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.BodyPart) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.BodyPart, "Body Parts"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.CallingCard) return true; return false; })) + { + XInventoryFolder folder = CreateFolder(principalID, rootFolder.ID, (int)FolderType.CallingCard, "Calling Cards"); + folder = CreateFolder(principalID, folder.folderID, (int)FolderType.CallingCard, "Friends"); + CreateFolder(principalID, folder.folderID, (int)FolderType.CallingCard, "All"); + } + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Clothing) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.Clothing, "Clothing"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.CurrentOutfit) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.CurrentOutfit, "Current Outfit"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Favorites) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.Favorites, "Favorites"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Gesture) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.Gesture, "Gestures"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Landmark) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.Landmark, "Landmarks"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.LostAndFound) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.LostAndFound, "Lost And Found"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Notecard) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.Notecard, "Notecards"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Object) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.Object, "Objects"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Snapshot) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.Snapshot, "Photo Album"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.LSLText) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.LSLText, "Scripts"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Sound) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.Sound, "Sounds"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Texture) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.Texture, "Textures"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Trash) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)FolderType.Trash, "Trash"); return result; } @@ -220,7 +228,7 @@ namespace OpenSim.Services.InventoryService XInventoryFolder root = null; foreach (XInventoryFolder folder in folders) { - if (folder.folderName == "My Inventory") + if (folder.folderName == InventoryFolderBase.ROOT_FOLDER_NAME) { root = folder; break; @@ -233,7 +241,7 @@ namespace OpenSim.Services.InventoryService return ConvertToOpenSim(root); } - public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) + public virtual InventoryFolderBase GetFolderForType(UUID principalID, FolderType type) { // m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID); @@ -251,11 +259,11 @@ namespace OpenSim.Services.InventoryService return GetSystemFolderForType(rootFolder, type); } - private InventoryFolderBase GetSystemFolderForType(InventoryFolderBase rootFolder, AssetType type) + private InventoryFolderBase GetSystemFolderForType(InventoryFolderBase rootFolder, FolderType type) { -// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID); - - if (type == AssetType.RootFolder) + //m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0}", type); + + if (type == FolderType.Root) return rootFolder; XInventoryFolder[] folders = m_Database.GetFolders( @@ -264,13 +272,13 @@ namespace OpenSim.Services.InventoryService if (folders.Length == 0) { -// m_log.WarnFormat("[XINVENTORY SERVICE]: Found no folder for type {0} for user {1}", type, principalID); + //m_log.WarnFormat("[XINVENTORY SERVICE]: Found no folder for type {0} ", type); return null; } - -// m_log.DebugFormat( -// "[XINVENTORY SERVICE]: Found folder {0} {1} for type {2} for user {3}", -// folders[0].folderName, folders[0].folderID, type, principalID); + + //m_log.DebugFormat( + // "[XINVENTORY SERVICE]: Found folder {0} {1} for type {2}", + // folders[0].folderName, folders[0].folderID, type); return ConvertToOpenSim(folders[0]); } @@ -283,7 +291,7 @@ namespace OpenSim.Services.InventoryService // //m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString()); InventoryCollection inventory = new InventoryCollection(); - inventory.UserID = principalID; + inventory.OwnerID = principalID; inventory.Folders = new List(); inventory.Items = new List(); @@ -307,8 +315,27 @@ namespace OpenSim.Services.InventoryService inventory.Items.Add(ConvertToOpenSim(i)); } + InventoryFolderBase f = new InventoryFolderBase(folderID, principalID); + f = GetFolder(f); + if (f != null) + { + inventory.Version = f.Version; + inventory.OwnerID = f.Owner; + } + inventory.FolderID = folderID; + return inventory; } + + public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs) + { + InventoryCollection[] multiple = new InventoryCollection[folderIDs.Length]; + int i = 0; + foreach (UUID fid in folderIDs) + multiple[i++] = GetFolderContent(principalID, fid); + + return multiple; + } public virtual List GetFolderItems(UUID principalID, UUID folderID) { @@ -336,7 +363,7 @@ namespace OpenSim.Services.InventoryService if (check != null) return false; - if (folder.Type != (short)AssetType.Folder && folder.Type != (short)AssetType.Unknown) + if (folder.Type != (short)FolderType.None) { InventoryFolderBase rootFolder = GetRootFolder(folder.Owner); @@ -353,7 +380,7 @@ namespace OpenSim.Services.InventoryService if (folder.ParentID == rootFolder.ID) { InventoryFolderBase existingSystemFolder - = GetSystemFolderForType(rootFolder, (AssetType)folder.Type); + = GetSystemFolderForType(rootFolder, (FolderType)folder.Type); if (existingSystemFolder != null) { @@ -380,8 +407,8 @@ namespace OpenSim.Services.InventoryService if (check == null) return AddFolder(folder); - if ((check.Type != (short)AssetType.Unknown || xFolder.type != (short)AssetType.Unknown) - && (check.Type != (short)AssetType.OutfitFolder || xFolder.type != (short)AssetType.OutfitFolder)) + if ((check.Type != (short)FolderType.None || xFolder.type != (short)FolderType.None) + && (check.Type != (short)FolderType.Outfit || xFolder.type != (short)FolderType.Outfit)) { if (xFolder.version < check.Version) { @@ -583,6 +610,21 @@ namespace OpenSim.Services.InventoryService return ConvertToOpenSim(items[0]); } + public virtual InventoryItemBase[] GetMultipleItems(UUID userID, UUID[] ids) + { + InventoryItemBase[] items = new InventoryItemBase[ids.Length]; + int i = 0; + InventoryItemBase item = new InventoryItemBase(); + item.Owner = userID; + foreach (UUID id in ids) + { + item.ID = id; + items[i++] = GetItem(item); + } + + return items; + } + public virtual InventoryFolderBase GetFolder(InventoryFolderBase folder) { XInventoryFolder[] folders = m_Database.GetFolders( @@ -615,34 +657,6 @@ namespace OpenSim.Services.InventoryService return m_Database.GetAssetPermissions(principalID, assetID); } - public virtual InventoryCollection GetUserInventory(UUID userID) - { - InventoryCollection userInventory = new InventoryCollection(); - userInventory.UserID = userID; - userInventory.Folders = new List(); - userInventory.Items = new List(); - - List skel = GetInventorySkeleton(userID); - if (skel != null) - { - foreach (InventoryFolderBase f in skel) - { - InventoryCollection c = GetFolderContent(userID, f.ID); - if (c != null && c.Items != null && c.Items.Count > 0) - userInventory.Items.AddRange(c.Items); - if (c != null && c.Folders != null && c.Folders.Count > 0) - userInventory.Folders.AddRange(c.Folders); - } - } - m_log.DebugFormat("[XINVENTORY SERVICE]: GetUserInventory for user {0} returning {1} folders and {2} items", - userID, userInventory.Folders.Count, userInventory.Items.Count); - return userInventory; - } - - public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) - { - } - // Unused. // public bool HasInventoryForUser(UUID userID) @@ -658,9 +672,9 @@ namespace OpenSim.Services.InventoryService newFolder.ParentID = folder.parentFolderID; newFolder.Type = (short)folder.type; - // Viewer can't understand anything that's not in it's LLFolderType enum - if (newFolder.Type == 100) - newFolder.Type = -1; + //// Viewer can't understand anything that's not in it's LLFolderType enum + //if (newFolder.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) + // newFolder.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; newFolder.Version = (ushort)folder.version; newFolder.Name = folder.folderName; newFolder.Owner = folder.agentID; @@ -751,7 +765,7 @@ namespace OpenSim.Services.InventoryService if (folder.Length < 1) return false; - if (folder[0].type == (int)AssetType.TrashFolder) + if (folder[0].type == (int)FolderType.Trash) return true; UUID parentFolder = folder[0].parentFolderID; @@ -762,9 +776,9 @@ namespace OpenSim.Services.InventoryService if (parent.Length < 1) return false; - if (parent[0].type == (int)AssetType.TrashFolder) + if (parent[0].type == (int)FolderType.Trash) return true; - if (parent[0].type == (int)AssetType.RootFolder) + if (parent[0].type == (int)FolderType.Root) return false; parentFolder = parent[0].parentFolderID; diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index 9ec744f..c3756d0 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -190,6 +190,8 @@ namespace OpenSim.Services.LLLoginService private BuddyList m_buddyList = null; private string currency; + private string classifiedFee; + private int maxAgentGroups; static LLLoginResponse() { @@ -226,8 +228,8 @@ namespace OpenSim.Services.LLLoginService public LLLoginResponse(UserAccount account, AgentCircuitData aCircuit, GridUserInfo pinfo, GridRegion destination, List invSkel, FriendInfo[] friendsList, ILibraryService libService, string where, string startlocation, Vector3 position, Vector3 lookAt, List gestures, string message, - GridRegion home, IPEndPoint clientIP, string mapTileURL, string profileURL, string openIDURL, string searchURL, string currency, - string DSTZone) + GridRegion home, IPEndPoint clientIP, string mapTileURL, string searchURL, string currency, + string DSTZone, string destinationsURL, string avatarsURL, string classifiedFee, int maxAgentGroups) : this() { FillOutInventoryData(invSkel, libService); @@ -246,14 +248,19 @@ namespace OpenSim.Services.LLLoginService MapTileURL = mapTileURL; ProfileURL = profileURL; OpenIDURL = openIDURL; + DestinationsURL = destinationsURL; + AvatarsURL = avatarsURL; SearchURL = searchURL; Currency = currency; + ClassifiedFee = classifiedFee; + MaxAgentGroups = maxAgentGroups; FillOutHomeData(pinfo, home); LookAt = String.Format("[r{0},r{1},r{2}]", lookAt.X, lookAt.Y, lookAt.Z); FillOutRegionData(destination); + m_log.DebugFormat("[LOGIN RESPONSE] LLLoginResponse create. sizeX={0}, sizeY={1}", RegionSizeX, RegionSizeY); FillOutSeedCap(aCircuit, destination, clientIP); @@ -356,7 +363,8 @@ namespace OpenSim.Services.LLLoginService private void FillOutHomeData(GridUserInfo pinfo, GridRegion home) { - int x = 1000 * (int)Constants.RegionSize, y = 1000 * (int)Constants.RegionSize; + int x = (int)Util.RegionToWorldLoc(1000); + int y = (int)Util.RegionToWorldLoc(1000); if (home != null) { x = home.RegionLocX; @@ -379,6 +387,8 @@ namespace OpenSim.Services.LLLoginService SimPort = (uint)endPoint.Port; RegionX = (uint)destination.RegionLocX; RegionY = (uint)destination.RegionLocY; + RegionSizeX = destination.RegionSizeX; + RegionSizeY = destination.RegionSizeY; } private void FillOutSeedCap(AgentCircuitData aCircuit, GridRegion destination, IPEndPoint ipepClient) @@ -428,10 +438,23 @@ namespace OpenSim.Services.LLLoginService ErrorReason = "key"; welcomeMessage = "Welcome to OpenSim!"; seedCapability = String.Empty; - home = "{'region_handle':[r" + (1000*Constants.RegionSize).ToString() + ",r" + (1000*Constants.RegionSize).ToString() + "], 'position':[r" + - userProfile.homepos.X.ToString() + ",r" + userProfile.homepos.Y.ToString() + ",r" + - userProfile.homepos.Z.ToString() + "], 'look_at':[r" + userProfile.homelookat.X.ToString() + ",r" + - userProfile.homelookat.Y.ToString() + ",r" + userProfile.homelookat.Z.ToString() + "]}"; + home = "{'region_handle':[" + + "r" + Util.RegionToWorldLoc(1000).ToString() + + "," + + "r" + Util.RegionToWorldLoc(1000).ToString() + + "], 'position':[" + + "r" + userProfile.homepos.X.ToString() + + "," + + "r" + userProfile.homepos.Y.ToString() + + "," + + "r" + userProfile.homepos.Z.ToString() + + "], 'look_at':[" + + "r" + userProfile.homelookat.X.ToString() + + "," + + "r" + userProfile.homelookat.Y.ToString() + + "," + + "r" + userProfile.homelookat.Z.ToString() + + "]}"; lookAt = "[r0.99949799999999999756,r0.03166859999999999814,r0]"; RegionX = (uint) 255232; RegionY = (uint) 254976; @@ -461,6 +484,8 @@ namespace OpenSim.Services.LLLoginService searchURL = String.Empty; currency = String.Empty; + ClassifiedFee = "0"; + MaxAgentGroups = 42; } @@ -520,9 +545,13 @@ namespace OpenSim.Services.LLLoginService responseData["seed_capability"] = seedCapability; responseData["home"] = home; responseData["look_at"] = lookAt; + responseData["max-agent-groups"] = MaxAgentGroups; responseData["message"] = welcomeMessage; responseData["region_x"] = (Int32)(RegionX); responseData["region_y"] = (Int32)(RegionY); + responseData["region_size_x"] = (Int32)RegionSizeX; + responseData["region_size_y"] = (Int32)RegionSizeY; + m_log.DebugFormat("[LOGIN RESPONSE] returning sizeX={0}, sizeY={1}", RegionSizeX, RegionSizeY); if (searchURL != String.Empty) responseData["search"] = searchURL; @@ -533,6 +562,12 @@ namespace OpenSim.Services.LLLoginService if (profileURL != String.Empty) responseData["profile-server-url"] = profileURL; + if (DestinationsURL != String.Empty) + responseData["destination_guide_url"] = DestinationsURL; + + if (AvatarsURL != String.Empty) + responseData["avatar_picker_url"] = AvatarsURL; + // We need to send an openid_token back in the response too if (openIDURL != String.Empty) responseData["openid_url"] = openIDURL; @@ -547,6 +582,9 @@ namespace OpenSim.Services.LLLoginService // responseData["real_currency"] = currency; responseData["currency"] = currency; } + + if (ClassifiedFee != String.Empty) + responseData["classified_fee"] = ClassifiedFee; responseData["login"] = "true"; @@ -635,6 +673,7 @@ namespace OpenSim.Services.LLLoginService map["seed_capability"] = OSD.FromString(seedCapability); map["home"] = OSD.FromString(home); map["look_at"] = OSD.FromString(lookAt); + map["max-agent-groups"] = OSD.FromInteger(MaxAgentGroups); map["message"] = OSD.FromString(welcomeMessage); map["region_x"] = OSD.FromInteger(RegionX); map["region_y"] = OSD.FromInteger(RegionY); @@ -651,6 +690,9 @@ namespace OpenSim.Services.LLLoginService if (searchURL != String.Empty) map["search"] = OSD.FromString(searchURL); + if (ClassifiedFee != String.Empty) + map["classified_fee"] = OSD.FromString(ClassifiedFee); + if (m_buddyList != null) { map["buddy-list"] = ArrayListToOSDArray(m_buddyList.ToArray()); @@ -746,7 +788,7 @@ namespace OpenSim.Services.LLLoginService Hashtable TempHash; foreach (InventoryFolderBase InvFolder in folders) { - if (InvFolder.ParentID == UUID.Zero && InvFolder.Name == "My Inventory") + if (InvFolder.ParentID == UUID.Zero && InvFolder.Name == InventoryFolderBase.ROOT_FOLDER_NAME) { rootID = InvFolder.ID; } @@ -900,6 +942,9 @@ namespace OpenSim.Services.LLLoginService set { regionY = value; } } + public int RegionSizeX { get; private set; } + public int RegionSizeY { get; private set; } + public string SunTexture { get { return sunTexture; } @@ -1056,6 +1101,28 @@ namespace OpenSim.Services.LLLoginService set { currency = value; } } + public string ClassifiedFee + { + get { return classifiedFee; } + set { classifiedFee = value; } + } + + public int MaxAgentGroups + { + get { return maxAgentGroups; } + set { maxAgentGroups = value; } + } + + public string DestinationsURL + { + get; set; + } + + public string AvatarsURL + { + get; set; + } + #endregion public class UserInfo diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 59fb559..0b38738 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -50,12 +50,15 @@ namespace OpenSim.Services.LLLoginService public class LLLoginService : ILoginService { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly string LogHeader = "[LLOGIN SERVICE]"; + private static bool Initialized = false; protected IUserAccountService m_UserAccountService; protected IGridUserService m_GridUserService; protected IAuthenticationService m_AuthenticationService; protected IInventoryService m_InventoryService; + protected IInventoryService m_HGInventoryService; protected IGridService m_GridService; protected IPresenceService m_PresenceService; protected ISimulationService m_LocalSimulationService; @@ -74,14 +77,15 @@ namespace OpenSim.Services.LLLoginService protected string m_GatekeeperURL; protected bool m_AllowRemoteSetLoginLevel; protected string m_MapTileURL; - protected string m_ProfileURL; - protected string m_OpenIDURL; protected string m_SearchURL; protected string m_Currency; - + protected string m_ClassifiedFee; + protected int m_MaxAgentGroups; + protected string m_DestinationGuide; + protected string m_AvatarPicker; protected string m_AllowedClients; protected string m_DeniedClients; - + protected string m_MessageUrl; protected string m_DSTZone; IConfig m_LoginServerConfig; @@ -110,18 +114,29 @@ namespace OpenSim.Services.LLLoginService m_RequireInventory = m_LoginServerConfig.GetBoolean("RequireInventory", true); m_AllowRemoteSetLoginLevel = m_LoginServerConfig.GetBoolean("AllowRemoteSetLoginLevel", false); m_MinLoginLevel = m_LoginServerConfig.GetInt("MinLoginLevel", 0); - m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty); + m_GatekeeperURL = Util.GetConfigVarFromSections(config, "GatekeeperURI", + new string[] { "Startup", "Hypergrid", "LoginService" }, String.Empty); m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty); - m_ProfileURL = m_LoginServerConfig.GetString("ProfileServerURL", string.Empty); - m_OpenIDURL = m_LoginServerConfig.GetString("OpenIDServerURL", String.Empty); m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty); m_Currency = m_LoginServerConfig.GetString("Currency", string.Empty); + m_ClassifiedFee = m_LoginServerConfig.GetString("ClassifiedFee", string.Empty); + m_DestinationGuide = m_LoginServerConfig.GetString ("DestinationGuide", string.Empty); + m_AvatarPicker = m_LoginServerConfig.GetString ("AvatarPicker", string.Empty); - m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty); - m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty); + string[] possibleAccessControlConfigSections = new string[] { "AccessControl", "LoginService" }; + m_AllowedClients = Util.GetConfigVarFromSections( + config, "AllowedClients", possibleAccessControlConfigSections, string.Empty); + m_DeniedClients = Util.GetConfigVarFromSections( + config, "DeniedClients", possibleAccessControlConfigSections, string.Empty); + m_MessageUrl = m_LoginServerConfig.GetString("MessageUrl", string.Empty); m_DSTZone = m_LoginServerConfig.GetString("DSTZone", "America/Los_Angeles;Pacific Standard Time"); + IConfig groupConfig = config.Configs["Groups"]; + if (groupConfig != null) + m_MaxAgentGroups = groupConfig.GetInt("MaxAgentGroups", 42); + + // Clean up some of these vars if (m_MapTileURL != String.Empty) { @@ -156,6 +171,15 @@ namespace OpenSim.Services.LLLoginService if (agentService != string.Empty) m_UserAgentService = ServerUtils.LoadPlugin(agentService, args); + // Get the Hypergrid inventory service (exists only if Hypergrid is enabled) + string hgInvServicePlugin = m_LoginServerConfig.GetString("HGInventoryServicePlugin", String.Empty); + if (hgInvServicePlugin != string.Empty) + { + string hgInvServiceArg = m_LoginServerConfig.GetString("HGInventoryServiceConstructorArg", String.Empty); + Object[] args2 = new Object[] { config, hgInvServiceArg }; + m_HGInventoryService = ServerUtils.LoadPlugin(hgInvServicePlugin, args2); + } + // // deal with the services given as argument // @@ -241,6 +265,7 @@ namespace OpenSim.Services.LLLoginService { bool success = false; UUID session = UUID.Random(); + string processedMessage; m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} at {2} using viewer {3}, channel {4}, IP {5}, Mac {6}, Id0 {7}", firstName, lastName, startLocation, clientVersion, channel, clientIP.Address.ToString(), mac, id0); @@ -341,6 +366,13 @@ namespace OpenSim.Services.LLLoginService return LLFailedLoginResponse.InventoryProblem; } + if (m_HGInventoryService != null) + { + // Give the Suitcase service a chance to create the suitcase folder. + // (If we're not using the Suitcase inventory service then this won't do anything.) + m_HGInventoryService.GetRootFolder(account.PrincipalID); + } + List inventorySkel = m_InventoryService.GetInventorySkeleton(account.PrincipalID); if (m_RequireInventory && ((inventorySkel == null) || (inventorySkel != null && inventorySkel.Count == 0))) { @@ -375,13 +407,33 @@ namespace OpenSim.Services.LLLoginService // GridRegion home = null; GridUserInfo guinfo = m_GridUserService.LoggedIn(account.PrincipalID.ToString()); - if (guinfo != null && (guinfo.HomeRegionID != UUID.Zero) && m_GridService != null) + + // We are only going to complain about no home if the user actually tries to login there, to avoid + // spamming the console. + if (guinfo != null) { - home = m_GridService.GetRegionByUUID(scopeID, guinfo.HomeRegionID); + if (guinfo.HomeRegionID == UUID.Zero && startLocation == "home") + { + m_log.WarnFormat( + "[LLOGIN SERVICE]: User {0} tried to login to a 'home' start location but they have none set", + account.Name); + } + else if (m_GridService != null) + { + home = m_GridService.GetRegionByUUID(scopeID, guinfo.HomeRegionID); + + if (home == null && startLocation == "home") + { + m_log.WarnFormat( + "[LLOGIN SERVICE]: User {0} tried to login to a 'home' start location with ID {1} but this was not found.", + account.Name, guinfo.HomeRegionID); + } + } } - if (guinfo == null) + else { // something went wrong, make something up, so that we don't have to test this anywhere else + m_log.DebugFormat("{0} Failed to fetch GridUserInfo. Creating empty GridUserInfo as home", LogHeader); guinfo = new GridUserInfo(); guinfo.LastPosition = guinfo.HomePosition = new Vector3(128, 128, 30); } @@ -448,16 +500,28 @@ namespace OpenSim.Services.LLLoginService // // Finally, fill out the response and return it // + if (m_MessageUrl != String.Empty) + { + WebClient client = new WebClient(); + processedMessage = client.DownloadString(m_MessageUrl); + } + else + { + processedMessage = m_WelcomeMessage; + } + processedMessage = processedMessage.Replace("\\n", "\n").Replace("", firstName + " " + lastName); + LLLoginResponse response - = new LLLoginResponse( - account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService, - where, startLocation, position, lookAt, gestures, m_WelcomeMessage, home, clientIP, - m_MapTileURL, m_ProfileURL, m_OpenIDURL, m_SearchURL, m_Currency, m_DSTZone); + = new LLLoginResponse( + account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService, + where, startLocation, position, lookAt, gestures, processedMessage, home, clientIP, + m_MapTileURL, m_SearchURL, m_Currency, m_DSTZone, + m_DestinationGuide, m_AvatarPicker, m_ClassifiedFee, m_MaxAgentGroups); - m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to {0} {1}", firstName, lastName); + m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to {0} {1}", firstName, lastName); - return response; - } + return response; + } catch (Exception e) { m_log.WarnFormat("[LLOGIN SERVICE]: Exception processing login for {0} {1}: {2} {3}", firstName, lastName, e.ToString(), e.StackTrace); @@ -498,10 +562,6 @@ namespace OpenSim.Services.LLLoginService if (home == null) { - m_log.WarnFormat( - "[LLOGIN SERVICE]: User {0} {1} tried to login to a 'home' start location but they have none set", - account.FirstName, account.LastName); - tryDefaults = true; } else @@ -576,7 +636,7 @@ namespace OpenSim.Services.LLLoginService // e.g. New Moon&135&46 New Moon@osgrid.org:8002&153&34 where = "url"; GridRegion region = null; - Regex reURI = new Regex(@"^uri:(?[^&]+)&(?\d+)&(?\d+)&(?\d+)$"); + Regex reURI = new Regex(@"^uri:(?[^&]+)&(?\d+[.]?\d*)&(?\d+[.]?\d*)&(?\d+[.]?\d*)$"); Match uriMatch = reURI.Match(startLocation); if (uriMatch == null) { @@ -645,8 +705,7 @@ namespace OpenSim.Services.LLLoginService if (parts.Length > 1) UInt32.TryParse(parts[1], out port); -// GridRegion region = FindForeignRegion(domainName, port, regionName, out gatekeeper); - region = FindForeignRegion(domainName, port, regionName, out gatekeeper); + region = FindForeignRegion(domainName, port, regionName, account, out gatekeeper); return region; } } @@ -673,7 +732,7 @@ namespace OpenSim.Services.LLLoginService private GridRegion FindAlternativeRegion(UUID scopeID) { List hyperlinks = null; - List regions = m_GridService.GetFallbackRegions(scopeID, 1000 * (int)Constants.RegionSize, 1000 * (int)Constants.RegionSize); + List regions = m_GridService.GetFallbackRegions(scopeID, (int)Util.RegionToWorldLoc(1000), (int)Util.RegionToWorldLoc(1000)); if (regions != null && regions.Count > 0) { hyperlinks = m_GridService.GetHyperlinks(scopeID); @@ -695,7 +754,7 @@ namespace OpenSim.Services.LLLoginService return null; } - private GridRegion FindForeignRegion(string domainName, uint port, string regionName, out GridRegion gatekeeper) + private GridRegion FindForeignRegion(string domainName, uint port, string regionName, UserAccount account, out GridRegion gatekeeper) { m_log.Debug("[LLLOGIN SERVICE]: attempting to findforeignregion " + domainName + ":" + port.ToString() + ":" + regionName); gatekeeper = new GridRegion(); @@ -707,9 +766,14 @@ namespace OpenSim.Services.LLLoginService UUID regionID; ulong handle; string imageURL = string.Empty, reason = string.Empty; + string message; if (m_GatekeeperConnector.LinkRegion(gatekeeper, out regionID, out handle, out domainName, out imageURL, out reason)) { - GridRegion destination = m_GatekeeperConnector.GetHyperlinkRegion(gatekeeper, regionID); + string homeURI = null; + if (account.ServiceURLs != null && account.ServiceURLs.ContainsKey("HomeURI")) + homeURI = (string)account.ServiceURLs["HomeURI"]; + + GridRegion destination = m_GatekeeperConnector.GetHyperlinkRegion(gatekeeper, regionID, account.PrincipalID, homeURI, out message); return destination; } @@ -858,13 +922,6 @@ namespace OpenSim.Services.LLLoginService SetServiceURLs(aCircuit, account); return aCircuit; - - //m_UserAgentService.LoginAgentToGrid(aCircuit, GatekeeperServiceConnector, region, out reason); - //if (simConnector.CreateAgent(region, aCircuit, 0, out reason)) - // return aCircuit; - - //return null; - } private void SetServiceURLs(AgentCircuitData aCircuit, UserAccount account) @@ -899,7 +956,7 @@ namespace OpenSim.Services.LLLoginService if (!keyValue.EndsWith("/")) keyValue = keyValue + "/"; - if (!account.ServiceURLs.ContainsKey(keyName) || (account.ServiceURLs.ContainsKey(keyName) && account.ServiceURLs[keyName] != keyValue)) + if (!account.ServiceURLs.ContainsKey(keyName) || (account.ServiceURLs.ContainsKey(keyName) && (string)account.ServiceURLs[keyName] != keyValue)) { account.ServiceURLs[keyName] = keyValue; newUrls = true; @@ -909,6 +966,13 @@ namespace OpenSim.Services.LLLoginService m_log.DebugFormat("[LLLOGIN SERVICE]: found new key {0} {1}", keyName, aCircuit.ServiceURLs[keyName]); } + if (!account.ServiceURLs.ContainsKey("GatekeeperURI") && !string.IsNullOrEmpty(m_GatekeeperURL)) + { + m_log.DebugFormat("[LLLOGIN SERVICE]: adding gatekeeper uri {0}", m_GatekeeperURL); + account.ServiceURLs["GatekeeperURI"] = m_GatekeeperURL; + newUrls = true; + } + // The grid operator decided to override the defaults in the // [LoginService] configuration. Let's store the correct ones. if (newUrls) @@ -919,13 +983,20 @@ namespace OpenSim.Services.LLLoginService private bool LaunchAgentDirectly(ISimulationService simConnector, GridRegion region, AgentCircuitData aCircuit, TeleportFlags flags, out string reason) { - return simConnector.CreateAgent(region, aCircuit, (uint)flags, out reason); + EntityTransferContext ctx = new EntityTransferContext(); + + if (!simConnector.QueryAccess( + region, aCircuit.AgentID, null, true, aCircuit.startpos, new List(), ctx, out reason)) + return false; + + return simConnector.CreateAgent(null, region, aCircuit, (uint)flags, out reason); } private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason) { - m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName); - if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, clientIP, out reason)) + m_log.Debug("[LLOGIN SERVICE]: Launching agent at " + destination.RegionName); + + if (m_UserAgentService.LoginAgentToGrid(null, aCircuit, gatekeeper, destination, true, out reason)) return true; return false; } @@ -961,14 +1032,25 @@ namespace OpenSim.Services.LLLoginService // or fixing critical issues // if (cmd.Length > 2) - Int32.TryParse(cmd[2], out m_MinLoginLevel); + { + if (Int32.TryParse(cmd[2], out m_MinLoginLevel)) + MainConsole.Instance.OutputFormat("Set minimum login level to {0}", m_MinLoginLevel); + else + MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid login level", cmd[2]); + } break; - case "reset": + + case "reset": m_MinLoginLevel = 0; + MainConsole.Instance.OutputFormat("Reset min login level to {0}", m_MinLoginLevel); break; + case "text": if (cmd.Length > 2) + { m_WelcomeMessage = cmd[2]; + MainConsole.Instance.OutputFormat("Login welcome message set to '{0}'", m_WelcomeMessage); + } break; } } diff --git a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs index 62c6e0f..5c150e3 100644 --- a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs index a85ee70..a816411 100644 --- a/OpenSim/Services/MapImageService/MapImageService.cs +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -36,6 +36,7 @@ using System.Drawing.Imaging; using System.IO; using System.Net; using System.Reflection; +using System.Threading; using Nini.Config; using log4net; @@ -53,6 +54,9 @@ namespace OpenSim.Services.MapImageService private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); +#pragma warning disable 414 + private string LogHeader = "[MAP IMAGE SERVICE]"; +#pragma warning restore 414 private const int ZOOM_LEVELS = 8; private const int IMAGE_WIDTH = 256; @@ -86,7 +90,7 @@ namespace OpenSim.Services.MapImageService { Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH); FillImage(waterTile, m_Watercolor); - waterTile.Save(m_WaterTileFile); + waterTile.Save(m_WaterTileFile, ImageFormat.Jpeg); } } } @@ -112,28 +116,106 @@ namespace OpenSim.Services.MapImageService reason = e.Message; return false; } + } + + return UpdateMultiResolutionFilesAsync(x, y, out reason); + } - // Also save in png format? + public bool RemoveMapTile(int x, int y, out string reason) + { + reason = String.Empty; + string fileName = GetFileName(1, x, y); - // Stitch seven more aggregate tiles together - for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++) + lock (m_Sync) + { + try + { + File.Delete(fileName); + } + catch (Exception e) { - // Calculate the width (in full resolution tiles) and bottom-left - // corner of the current zoom level - int width = (int)Math.Pow(2, (double)(zoomLevel - 1)); - int x1 = x - (x % width); - int y1 = y - (y % width); + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to save delete file {0}: {1}", fileName, e); + reason = e.Message; + return false; + } + } + + return UpdateMultiResolutionFilesAsync(x, y, out reason); + } - if (!CreateTile(zoomLevel, x1, y1)) + // When large varregions start up, they can send piles of new map tiles. This causes + // this multi-resolution routine to be called a zillion times an causes much CPU + // time to be spent creating multi-resolution tiles that will be replaced when + // the next maptile arrives. + private class mapToMultiRez + { + public int xx; + public int yy; + public mapToMultiRez(int pX, int pY) + { + xx = pX; + yy = pY; + } + }; + private Queue multiRezToBuild = new Queue(); + private bool UpdateMultiResolutionFilesAsync(int x, int y, out string reason) + { + reason = String.Empty; + lock (multiRezToBuild) + { + // m_log.DebugFormat("{0} UpdateMultiResolutionFilesAsync: scheduling update for <{1},{2}>", LogHeader, x, y); + multiRezToBuild.Enqueue(new mapToMultiRez(x, y)); + if (multiRezToBuild.Count == 1) + Util.FireAndForget( + DoUpdateMultiResolutionFilesAsync, null, "MapImageService.DoUpdateMultiResolutionFilesAsync"); + } + + return true; + } + + private void DoUpdateMultiResolutionFilesAsync(object o) + { + // This sleep causes the FireAndForget thread to be different than the invocation thread. + // It also allows other tiles to be uploaded so the multi-rez images are more likely + // to be correct. + Thread.Sleep(1 * 1000); + + while (multiRezToBuild.Count > 0) + { + mapToMultiRez toMultiRez = null; + lock (multiRezToBuild) + { + if (multiRezToBuild.Count > 0) + toMultiRez = multiRezToBuild.Dequeue(); + } + if (toMultiRez != null) + { + int x = toMultiRez.xx; + int y = toMultiRez.yy; + // m_log.DebugFormat("{0} DoUpdateMultiResolutionFilesAsync: doing build for <{1},{2}>", LogHeader, x, y); + + // Stitch seven more aggregate tiles together + for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++) { - m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0} at zoom level {1}", fileName, zoomLevel); - reason = string.Format("Map tile at zoom level {0} failed", zoomLevel); - return false; + // Calculate the width (in full resolution tiles) and bottom-left + // corner of the current zoom level + int width = (int)Math.Pow(2, (double)(zoomLevel - 1)); + int x1 = x - (x % width); + int y1 = y - (y % width); + + lock (m_Sync) // must lock the reading and writing of the maptile files + { + if (!CreateTile(zoomLevel, x1, y1)) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0},{1} at zoom level {1}", x, y, zoomLevel); + return; + } + } } } } - return true; + return; } public byte[] GetMapTile(string fileName, out string format) diff --git a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs index 23eb664..e779238 100644 --- a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/PresenceService/PresenceService.cs b/OpenSim/Services/PresenceService/PresenceService.cs index ed2703e..b5ca4d5 100644 --- a/OpenSim/Services/PresenceService/PresenceService.cs +++ b/OpenSim/Services/PresenceService/PresenceService.cs @@ -41,9 +41,7 @@ namespace OpenSim.Services.PresenceService { public class PresenceService : PresenceServiceBase, IPresenceService { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected bool m_allowDuplicatePresences = false; @@ -55,19 +53,15 @@ namespace OpenSim.Services.PresenceService IConfig presenceConfig = config.Configs["PresenceService"]; if (presenceConfig != null) { - m_allowDuplicatePresences = - presenceConfig.GetBoolean("AllowDuplicatePresences", - m_allowDuplicatePresences); + m_allowDuplicatePresences = presenceConfig.GetBoolean("AllowDuplicatePresences", m_allowDuplicatePresences); } } - public bool LoginAgent(string userID, UUID sessionID, - UUID secureSessionID) + public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID) { - //PresenceData[] d = m_Database.Get("UserID", userID); - //m_Database.Get("UserID", userID); + PresenceData prevUser = GetUser(userID); - if (!m_allowDuplicatePresences) + if (!m_allowDuplicatePresences && (prevUser != null)) m_Database.Delete("UserID", userID.ToString()); PresenceData data = new PresenceData(); @@ -80,19 +74,41 @@ namespace OpenSim.Services.PresenceService m_Database.Store(data); - m_log.DebugFormat("[PRESENCE SERVICE]: LoginAgent {0} with session {1} and ssession {2}", - userID, sessionID, secureSessionID); + string prevUserStr = ""; + if (prevUser != null) + prevUserStr = string.Format(". This user was already logged-in: session {0}, region {1}", prevUser.SessionID, prevUser.RegionID); + + m_log.DebugFormat("[PRESENCE SERVICE]: LoginAgent: session {0}, user {1}, region {2}, secure session {3}{4}", + data.SessionID, data.UserID, data.RegionID, secureSessionID, prevUserStr); + return true; } public bool LogoutAgent(UUID sessionID) { - m_log.DebugFormat("[PRESENCE SERVICE]: Session {0} logout", sessionID); + PresenceInfo presence = GetAgent(sessionID); + + m_log.InfoFormat("[PRESENCE SERVICE]: LogoutAgent: session {0}, user {1}, region {2}", + sessionID, + (presence == null) ? null : presence.UserID, + (presence == null) ? null : presence.RegionID.ToString()); + return m_Database.Delete("SessionID", sessionID.ToString()); } public bool LogoutRegionAgents(UUID regionID) { + PresenceData[] prevSessions = GetRegionAgents(regionID); + + if ((prevSessions == null) || (prevSessions.Length == 0)) + return true; + + m_log.DebugFormat("[PRESENCE SERVICE]: Logout users in region {0}: {1}", regionID, + string.Join(", ", Array.ConvertAll(prevSessions, session => session.UserID))); + + // There's a small chance that LogoutRegionAgents() will logout different users than the + // list that was logged above, but it's unlikely and not worth dealing with. + m_Database.LogoutRegionAgents(regionID); return true; @@ -101,20 +117,26 @@ namespace OpenSim.Services.PresenceService public bool ReportAgent(UUID sessionID, UUID regionID) { -// m_log.DebugFormat("[PRESENCE SERVICE]: ReportAgent with session {0} in region {1}", sessionID, regionID); try { - PresenceData pdata = m_Database.Get(sessionID); - if (pdata == null) - return false; - if (pdata.Data == null) - return false; + PresenceData presence = m_Database.Get(sessionID); + + bool success; + if (presence == null) + success = false; + else + success = m_Database.ReportAgent(sessionID, regionID); - return m_Database.ReportAgent(sessionID, regionID); + m_log.DebugFormat("[PRESENCE SERVICE]: ReportAgent{0}: session {1}, user {2}, region {3}. Previously: {4}", + success ? "" : " failed", + sessionID, (presence == null) ? null : presence.UserID, regionID, + (presence == null) ? "not logged-in" : "region " + presence.RegionID); + + return success; } catch (Exception e) { - m_log.DebugFormat("[PRESENCE SERVICE]: ReportAgent threw exception {0}", e.StackTrace); + m_log.Debug(string.Format("[PRESENCE SERVICE]: ReportAgent for session {0} threw exception ", sessionID), e); return false; } } @@ -139,8 +161,7 @@ namespace OpenSim.Services.PresenceService foreach (string userIDStr in userIDs) { - PresenceData[] data = m_Database.Get("UserID", - userIDStr); + PresenceData[] data = m_Database.Get("UserID", userIDStr); foreach (PresenceData d in data) { @@ -158,5 +179,23 @@ namespace OpenSim.Services.PresenceService return info.ToArray(); } + + /// + /// Return the user's Presence. This only really works well if !AllowDuplicatePresences, but that's the default. + /// + private PresenceData GetUser(string userID) + { + PresenceData[] data = m_Database.Get("UserID", userID); + if (data.Length > 0) + return data[0]; + else + return null; + } + + private PresenceData[] GetRegionAgents(UUID regionID) + { + return m_Database.Get("RegionID", regionID.ToString()); + } + } } \ No newline at end of file diff --git a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs index 8c03dd7..4fd21a8 100644 --- a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/SimulationService/SimulationDataService.cs b/OpenSim/Services/SimulationService/SimulationDataService.cs new file mode 100644 index 0000000..d9684c4 --- /dev/null +++ b/OpenSim/Services/SimulationService/SimulationDataService.cs @@ -0,0 +1,191 @@ +/* + * 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 OpenSimulator 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.Generic; +using OpenMetaverse; +using log4net; +using Nini.Config; +using System.Reflection; +using OpenSim.Services.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Services.SimulationService +{ + public class SimulationDataService : ServiceBase, ISimulationDataService + { +// private static readonly ILog m_log = +// LogManager.GetLogger( +// MethodBase.GetCurrentMethod().DeclaringType); + + protected ISimulationDataStore m_database; + + public SimulationDataService(IConfigSource config) + : base(config) + { + string dllName = String.Empty; + string connString = String.Empty; + + // Try reading the [DatabaseService] section, if it exists + IConfig dbConfig = config.Configs["DatabaseService"]; + if (dbConfig != null) + { + dllName = dbConfig.GetString("StorageProvider", String.Empty); + connString = dbConfig.GetString("ConnectionString", String.Empty); + } + + // Try reading the [SimulationDataStore] section + IConfig simConfig = config.Configs["SimulationDataStore"]; + if (simConfig != null) + { + dllName = simConfig.GetString("StorageProvider", dllName); + connString = simConfig.GetString("ConnectionString", connString); + } + + // We tried, but this doesn't exist. We can't proceed + if (dllName == String.Empty) + throw new Exception("No StorageProvider configured"); + + m_database = LoadPlugin(dllName, new Object[] { connString }); + if (m_database == null) + throw new Exception("Could not find a storage interface in the given module"); + } + + public void StoreObject(SceneObjectGroup obj, UUID regionUUID) + { + m_database.StoreObject(obj, regionUUID); + } + + public void RemoveObject(UUID uuid, UUID regionUUID) + { + m_database.RemoveObject(uuid, regionUUID); + } + + public void StorePrimInventory(UUID primID, ICollection items) + { + m_database.StorePrimInventory(primID, items); + } + + public List LoadObjects(UUID regionUUID) + { + return m_database.LoadObjects(regionUUID); + } + + public void StoreTerrain(TerrainData terrain, UUID regionID) + { + m_database.StoreTerrain(terrain, regionID); + } + + public void StoreTerrain(double[,] terrain, UUID regionID) + { + m_database.StoreTerrain(terrain, regionID); + } + + public double[,] LoadTerrain(UUID regionID) + { + return m_database.LoadTerrain(regionID); + } + + public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) + { + return m_database.LoadTerrain(regionID, pSizeX, pSizeY, pSizeZ); + } + + public void StoreLandObject(ILandObject Parcel) + { + m_database.StoreLandObject(Parcel); + } + + public void RemoveLandObject(UUID globalID) + { + m_database.RemoveLandObject(globalID); + } + + public List LoadLandObjects(UUID regionUUID) + { + return m_database.LoadLandObjects(regionUUID); + } + + public void StoreRegionSettings(RegionSettings rs) + { + m_database.StoreRegionSettings(rs); + } + + public RegionSettings LoadRegionSettings(UUID regionUUID) + { + return m_database.LoadRegionSettings(regionUUID); + } + + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) + { + return m_database.LoadRegionWindlightSettings(regionUUID); + } + + public void StoreRegionWindlightSettings(RegionLightShareData wl) + { + m_database.StoreRegionWindlightSettings(wl); + } + public void RemoveRegionWindlightSettings(UUID regionID) + { + m_database.RemoveRegionWindlightSettings(regionID); + } + + public string LoadRegionEnvironmentSettings(UUID regionUUID) + { + return m_database.LoadRegionEnvironmentSettings(regionUUID); + } + + public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) + { + m_database.StoreRegionEnvironmentSettings(regionUUID, settings); + } + + public void RemoveRegionEnvironmentSettings(UUID regionUUID) + { + m_database.RemoveRegionEnvironmentSettings(regionUUID); + } + + public void SaveExtra(UUID regionID, string name, string val) + { + m_database.SaveExtra(regionID, name, val); + } + + public void RemoveExtra(UUID regionID, string name) + { + m_database.RemoveExtra(regionID, name); + } + + public Dictionary GetExtra(UUID regionID) + { + return m_database.GetExtra(regionID); + } + } +} diff --git a/OpenSim/Services/UserAccountService/AgentPreferencesService.cs b/OpenSim/Services/UserAccountService/AgentPreferencesService.cs new file mode 100644 index 0000000..1808ee5 --- /dev/null +++ b/OpenSim/Services/UserAccountService/AgentPreferencesService.cs @@ -0,0 +1,82 @@ +/* + * 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 OpenSimulator 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.Generic; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Services.UserAccountService +{ + public class AgentPreferencesService : AgentPreferencesServiceBase, IAgentPreferencesService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public AgentPreferencesService(IConfigSource config) : base(config) + { + m_log.Debug("[AGENT PREFERENCES SERVICE]: Starting agent preferences service"); + } + + public AgentPrefs GetAgentPreferences(UUID principalID) + { + AgentPreferencesData d = m_Database.GetPrefs(principalID); + AgentPrefs prefs = (d == null) ? new AgentPrefs(principalID) : new AgentPrefs(d.Data); + return prefs; + } + + public bool StoreAgentPreferences(AgentPrefs data) + { + AgentPreferencesData d = new AgentPreferencesData(); + d.Data = new Dictionary(); + d.Data["PrincipalID"] = data.PrincipalID.ToString(); + d.Data["AccessPrefs"] = data.AccessPrefs; + d.Data["HoverHeight"] = data.HoverHeight.ToString(); + d.Data["Language"] = data.Language; + d.Data["LanguageIsPublic"] = (data.LanguageIsPublic ? "1" : "0"); + d.Data["PermEveryone"] = data.PermEveryone.ToString(); + d.Data["PermGroup"] = data.PermGroup.ToString(); + d.Data["PermNextOwner"] = data.PermNextOwner.ToString(); + return m_Database.Store(d); + } + + public string GetLang(UUID principalID) + { + AgentPrefs data = GetAgentPreferences(principalID); + if (data != null) + { + if (data.LanguageIsPublic) + return data.Language; + } + return "en-us"; + } + } +} diff --git a/OpenSim/Services/UserAccountService/AgentPreferencesServiceBase.cs b/OpenSim/Services/UserAccountService/AgentPreferencesServiceBase.cs new file mode 100644 index 0000000..5974349 --- /dev/null +++ b/OpenSim/Services/UserAccountService/AgentPreferencesServiceBase.cs @@ -0,0 +1,73 @@ +/* + * 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 OpenSimulator 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.Reflection; +using Nini.Config; +using OpenSim.Data; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Base; + +namespace OpenSim.Services.UserAccountService +{ + public class AgentPreferencesServiceBase: ServiceBase + { + protected IAgentPreferencesData m_Database = null; + + public AgentPreferencesServiceBase(IConfigSource config) : base(config) + { + string dllName = String.Empty; + string connString = String.Empty; + string realm = "AgentPrefs"; + + IConfig dbConfig = config.Configs["DatabaseService"]; + if (dbConfig != null) + { + dllName = dbConfig.GetString("StorageProvider", String.Empty); + connString = dbConfig.GetString("ConnectionString", String.Empty); + } + + IConfig userConfig = config.Configs["AgentPreferencesService"]; + if (userConfig == null) + throw new Exception("No AgentPreferencesService configuration"); + + dllName = userConfig.GetString("StorageProvider", dllName); + + if (dllName == String.Empty) + throw new Exception("No StorageProvider configured"); + + connString = userConfig.GetString("ConnectionString", connString); + + realm = userConfig.GetString("Realm", realm); + + m_Database = LoadPlugin(dllName, new Object[] {connString, realm}); + + if (m_Database == null) + throw new Exception("Could not find a storage interface in the given module"); + } + } +} diff --git a/OpenSim/Services/UserAccountService/GridUserService.cs b/OpenSim/Services/UserAccountService/GridUserService.cs index 43fa04b..80a9d9d 100644 --- a/OpenSim/Services/UserAccountService/GridUserService.cs +++ b/OpenSim/Services/UserAccountService/GridUserService.cs @@ -43,15 +43,117 @@ namespace OpenSim.Services.UserAccountService public class GridUserService : GridUserServiceBase, IGridUserService { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static bool m_Initialized; public GridUserService(IConfigSource config) : base(config) { - m_log.Debug("[USER GRID SERVICE]: Starting user grid service"); + m_log.Debug("[GRID USER SERVICE]: Starting user grid service"); + + if (!m_Initialized) + { + m_Initialized = true; + + MainConsole.Instance.Commands.AddCommand( + "Users", false, + "show grid user", + "show grid user ", + "Show grid user entry or entries that match or start with the given ID. This will normally be a UUID.", + "This is for debug purposes to see what data is found for a particular user id.", + HandleShowGridUser); + + MainConsole.Instance.Commands.AddCommand( + "Users", false, + "show grid users online", + "show grid users online", + "Show number of grid users registered as online.", + "This number may not be accurate as a region may crash or not be cleanly shutdown and leave grid users shown as online\n." + + "For this reason, users online for more than 5 days are not currently counted", + HandleShowGridUsersOnline); + } + } + + protected void HandleShowGridUser(string module, string[] cmdparams) + { + if (cmdparams.Length != 4) + { + MainConsole.Instance.Output("Usage: show grid user "); + return; + } + + GridUserData[] data = m_Database.GetAll(cmdparams[3]); + + foreach (GridUserData gu in data) + { + ConsoleDisplayList cdl = new ConsoleDisplayList(); + + cdl.AddRow("User ID", gu.UserID); + + foreach (KeyValuePair kvp in gu.Data) + cdl.AddRow(kvp.Key, kvp.Value); + + MainConsole.Instance.Output(cdl.ToString()); + } + + MainConsole.Instance.OutputFormat("Entries: {0}", data.Length); + } + + protected void HandleShowGridUsersOnline(string module, string[] cmdparams) + { +// if (cmdparams.Length != 4) +// { +// MainConsole.Instance.Output("Usage: show grid users online"); +// return; +// } + +// int onlineCount; + int onlineRecentlyCount = 0; + + DateTime now = DateTime.UtcNow; + + foreach (GridUserData gu in m_Database.GetAll("")) + { + if (bool.Parse(gu.Data["Online"])) + { +// onlineCount++; + + int unixLoginTime = int.Parse(gu.Data["Login"]); + + if ((now - Util.ToDateTime(unixLoginTime)).Days < 5) + onlineRecentlyCount++; + } + } + + MainConsole.Instance.OutputFormat("Users online: {0}", onlineRecentlyCount); + } + + private GridUserData GetGridUserData(string userID) + { + GridUserData d = null; + if (userID.Length > 36) // it's a UUI + { + d = m_Database.Get(userID); + } + else // it's a UUID + { + GridUserData[] ds = m_Database.GetAll(userID); + if (ds == null) + return null; + + if (ds.Length > 0) + { + d = ds[0]; + foreach (GridUserData dd in ds) + if (dd.UserID.Length > d.UserID.Length) // find the longest + d = dd; + } + } + + return d; } public virtual GridUserInfo GetGridUserInfo(string userID) { - GridUserData d = m_Database.Get(userID); + GridUserData d = GetGridUserData(userID); if (d == null) return null; @@ -73,7 +175,7 @@ namespace OpenSim.Services.UserAccountService return info; } - public GridUserInfo[] GetGridUserInfo(string[] userIDs) + public virtual GridUserInfo[] GetGridUserInfo(string[] userIDs) { List ret = new List(); @@ -86,7 +188,8 @@ namespace OpenSim.Services.UserAccountService public GridUserInfo LoggedIn(string userID) { m_log.DebugFormat("[GRID USER SERVICE]: User {0} is online", userID); - GridUserData d = m_Database.Get(userID); + + GridUserData d = GetGridUserData(userID); if (d == null) { @@ -104,8 +207,9 @@ namespace OpenSim.Services.UserAccountService public bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) { - m_log.DebugFormat("[GRID USER SERVICE]: User {0} is offline", userID); - GridUserData d = m_Database.Get(userID); + m_log.InfoFormat("[GRID USER SERVICE]: User {0} is offline", userID); + + GridUserData d = GetGridUserData(userID); if (d == null) { @@ -124,7 +228,8 @@ namespace OpenSim.Services.UserAccountService public bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt) { - GridUserData d = m_Database.Get(userID); + GridUserData d = GetGridUserData(userID); + if (d == null) { d = new GridUserData(); @@ -140,8 +245,10 @@ namespace OpenSim.Services.UserAccountService public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) { - //m_log.DebugFormat("[Grid User Service]: SetLastPosition for {0}", userID); - GridUserData d = m_Database.Get(userID); +// m_log.DebugFormat("[GRID USER SERVICE]: SetLastPosition for {0}", userID); + + GridUserData d = GetGridUserData(userID); + if (d == null) { d = new GridUserData(); @@ -155,4 +262,4 @@ namespace OpenSim.Services.UserAccountService return m_Database.Store(d); } } -} +} \ No newline at end of file diff --git a/OpenSim/Services/UserAccountService/GridUserServiceBase.cs b/OpenSim/Services/UserAccountService/GridUserServiceBase.cs index 990cb63..8c5f5df 100644 --- a/OpenSim/Services/UserAccountService/GridUserServiceBase.cs +++ b/OpenSim/Services/UserAccountService/GridUserServiceBase.cs @@ -60,12 +60,12 @@ namespace OpenSim.Services.UserAccountService // // [GridUsetService] section overrides [DatabaseService], if it exists // - IConfig presenceConfig = config.Configs["GridUserService"]; - if (presenceConfig != null) + IConfig usersConfig = config.Configs["GridUserService"]; + if (usersConfig != null) { - dllName = presenceConfig.GetString("StorageProvider", dllName); - connString = presenceConfig.GetString("ConnectionString", connString); - realm = presenceConfig.GetString("Realm", realm); + dllName = usersConfig.GetString("StorageProvider", dllName); + connString = usersConfig.GetString("ConnectionString", connString); + realm = usersConfig.GetString("Realm", realm); } // diff --git a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs index 24e1d16..6ca07a6 100644 --- a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs +++ b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("0.7.5.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.3.*")] + diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index 5b4d040..2e19ece 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -36,6 +36,7 @@ using OpenSim.Framework; using OpenSim.Services.Interfaces; using OpenSim.Framework.Console; using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using PermissionMask = OpenSim.Framework.PermissionMask; namespace OpenSim.Services.UserAccountService { @@ -97,7 +98,12 @@ namespace OpenSim.Services.UserAccountService MainConsole.Instance.Commands.AddCommand("Users", false, "reset user password", "reset user password [ [ []]]", - "Reset a user password", HandleResetUserPassword); + "Reset a user password", HandleResetUserPassword); + + MainConsole.Instance.Commands.AddCommand("Users", false, + "reset user email", + "reset user email [ [ []]]", + "Reset a user email address", HandleResetUserEmail); MainConsole.Instance.Commands.AddCommand("Users", false, "set user level", @@ -255,6 +261,10 @@ namespace OpenSim.Services.UserAccountService return MakeUserAccount(d[0]); } + public void InvalidateCache(UUID userID) + { + } + public bool StoreUserAccount(UserAccount data) { // m_log.DebugFormat( @@ -415,6 +425,43 @@ namespace OpenSim.Services.UserAccountService MainConsole.Instance.OutputFormat("Password reset for user {0} {1}", firstName, lastName); } + protected void HandleResetUserEmail(string module, string[] cmdparams) + { + string firstName; + string lastName; + string newEmail; + + if (cmdparams.Length < 4) + firstName = MainConsole.Instance.CmdPrompt("First name"); + else firstName = cmdparams[3]; + + if (cmdparams.Length < 5) + lastName = MainConsole.Instance.CmdPrompt("Last name"); + else lastName = cmdparams[4]; + + if (cmdparams.Length < 6) + newEmail = MainConsole.Instance.PasswdPrompt("New Email"); + else newEmail = cmdparams[5]; + + UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName); + if (account == null) + { + MainConsole.Instance.OutputFormat("No such user as {0} {1}", firstName, lastName); + return; + } + + bool success = false; + + account.Email = newEmail; + + success = StoreUserAccount(account); + if (!success) + MainConsole.Instance.OutputFormat("Unable to set Email for account {0} {1}.", firstName, lastName); + else + MainConsole.Instance.OutputFormat("User Email set for user {0} {1} to {2}", firstName, lastName, account.Email); + } + + protected void HandleSetUserLevel(string module, string[] cmdparams) { string firstName; @@ -475,7 +522,6 @@ namespace OpenSim.Services.UserAccountService { account.ServiceURLs = new Dictionary(); account.ServiceURLs["HomeURI"] = string.Empty; - account.ServiceURLs["GatekeeperURI"] = string.Empty; account.ServiceURLs["InventoryServerURI"] = string.Empty; account.ServiceURLs["AssetServerURI"] = string.Empty; } @@ -549,7 +595,7 @@ namespace OpenSim.Services.UserAccountService { m_log.DebugFormat("[USER ACCOUNT SERVICE]: Creating default appearance items for {0}", principalID); - InventoryFolderBase bodyPartsFolder = m_InventoryService.GetFolderForType(principalID, AssetType.Bodypart); + InventoryFolderBase bodyPartsFolder = m_InventoryService.GetFolderForType(principalID, FolderType.BodyPart); InventoryItemBase eyes = new InventoryItemBase(UUID.Random(), principalID); eyes.AssetID = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7"); @@ -611,7 +657,7 @@ namespace OpenSim.Services.UserAccountService hair.Flags = (uint)WearableType.Hair; m_InventoryService.AddItem(hair); - InventoryFolderBase clothingFolder = m_InventoryService.GetFolderForType(principalID, AssetType.Clothing); + InventoryFolderBase clothingFolder = m_InventoryService.GetFolderForType(principalID, FolderType.Clothing); InventoryItemBase shirt = new InventoryItemBase(UUID.Random(), principalID); shirt.AssetID = AvatarWearable.DEFAULT_SHIRT_ASSET; @@ -665,4 +711,4 @@ namespace OpenSim.Services.UserAccountService } } } -} \ No newline at end of file +} diff --git a/OpenSim/Services/UserProfilesService/UserProfilesService.cs b/OpenSim/Services/UserProfilesService/UserProfilesService.cs new file mode 100644 index 0000000..96c13c0 --- /dev/null +++ b/OpenSim/Services/UserProfilesService/UserProfilesService.cs @@ -0,0 +1,263 @@ +/* + * 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 OpenSimulator 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.Reflection; +using System.Text; +using Nini.Config; +using log4net; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Services.UserAccountService; +using OpenSim.Data; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; + +namespace OpenSim.Services.ProfilesService +{ + public class UserProfilesService: UserProfilesServiceBase, IUserProfilesService + { + static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + IUserAccountService userAccounts; + + public UserProfilesService(IConfigSource config, string configName): + base(config, configName) + { + IConfig Config = config.Configs[configName]; + if (Config == null) + { + m_log.Warn("[PROFILES SERVICE]: No configuration found!"); + return; + } + Object[] args = null; + + args = new Object[] { config }; + string accountService = Config.GetString("UserAccountService", String.Empty); + if (accountService != string.Empty) + userAccounts = ServerUtils.LoadPlugin(accountService, args); + + args = new Object[] { config }; + } + + #region Classifieds + public OSD AvatarClassifiedsRequest(UUID creatorId) + { + OSDArray records = ProfilesData.GetClassifiedRecords(creatorId); + + return records; + } + + public bool ClassifiedUpdate(UserClassifiedAdd ad, ref string result) + { + if(!ProfilesData.UpdateClassifiedRecord(ad, ref result)) + { + return false; + } + result = "success"; + return true; + } + + public bool ClassifiedDelete(UUID recordId) + { + if(ProfilesData.DeleteClassifiedRecord(recordId)) + return true; + + return false; + } + + public bool ClassifiedInfoRequest(ref UserClassifiedAdd ad, ref string result) + { + if(ProfilesData.GetClassifiedInfo(ref ad, ref result)) + return true; + + return false; + } + #endregion Classifieds + + #region Picks + public OSD AvatarPicksRequest(UUID creatorId) + { + OSDArray records = ProfilesData.GetAvatarPicks(creatorId); + + return records; + } + + public bool PickInfoRequest(ref UserProfilePick pick, ref string result) + { + pick = ProfilesData.GetPickInfo(pick.CreatorId, pick.PickId); + result = "OK"; + return true; + } + + public bool PicksUpdate(ref UserProfilePick pick, ref string result) + { + return ProfilesData.UpdatePicksRecord(pick); + } + + public bool PicksDelete(UUID pickId) + { + return ProfilesData.DeletePicksRecord(pickId); + } + #endregion Picks + + #region Notes + public bool AvatarNotesRequest(ref UserProfileNotes note) + { + return ProfilesData.GetAvatarNotes(ref note); + } + + public bool NotesUpdate(ref UserProfileNotes note, ref string result) + { + return ProfilesData.UpdateAvatarNotes(ref note, ref result); + } + #endregion Notes + + #region Profile Properties + public bool AvatarPropertiesRequest(ref UserProfileProperties prop, ref string result) + { + return ProfilesData.GetAvatarProperties(ref prop, ref result); + } + + public bool AvatarPropertiesUpdate(ref UserProfileProperties prop, ref string result) + { + return ProfilesData.UpdateAvatarProperties(ref prop, ref result); + } + #endregion Profile Properties + + #region Interests + public bool AvatarInterestsUpdate(UserProfileProperties prop, ref string result) + { + return ProfilesData.UpdateAvatarInterests(prop, ref result); + } + #endregion Interests + + #region User Preferences + public bool UserPreferencesUpdate(ref UserPreferences pref, ref string result) + { + if(string.IsNullOrEmpty(pref.EMail)) + { + UserAccount account = new UserAccount(); + if(userAccounts is UserAccountService.UserAccountService) + { + try + { + account = userAccounts.GetUserAccount(UUID.Zero, pref.UserId); + if(string.IsNullOrEmpty(account.Email)) + { + pref.EMail = string.Empty; + } + else + pref.EMail = account.Email; + } + catch + { + m_log.Error ("[PROFILES SERVICE]: UserAccountService Exception: Could not get user account"); + result = "UserAccountService settings error in UserProfileService!"; + return false; + } + } + else + { + m_log.Error ("[PROFILES SERVICE]: UserAccountService: Could not get user account"); + result = "UserAccountService settings error in UserProfileService!"; + return false; + } + } + return ProfilesData.UpdateUserPreferences(ref pref, ref result); + } + + public bool UserPreferencesRequest(ref UserPreferences pref, ref string result) + { + if (!ProfilesData.GetUserPreferences(ref pref, ref result)) + return false; + + if(string.IsNullOrEmpty(pref.EMail)) + { + UserAccount account = new UserAccount(); + if(userAccounts is UserAccountService.UserAccountService) + { + try + { + account = userAccounts.GetUserAccount(UUID.Zero, pref.UserId); + if(string.IsNullOrEmpty(account.Email)) + { + pref.EMail = string.Empty; + } + else + { + pref.EMail = account.Email; + UserPreferencesUpdate(ref pref, ref result); + } + } + catch + { + m_log.Error ("[PROFILES SERVICE]: UserAccountService Exception: Could not get user account"); + result = "UserAccountService settings error in UserProfileService!"; + return false; + } + } + else + { + m_log.Error ("[PROFILES SERVICE]: UserAccountService: Could not get user account"); + result = "UserAccountService settings error in UserProfileService!"; + return false; + } + } + + if(string.IsNullOrEmpty(pref.EMail)) + pref.EMail = "No Email Address On Record"; + + return true; + } + #endregion User Preferences + + #region Utility + public OSD AvatarImageAssetsRequest(UUID avatarId) + { + OSDArray records = ProfilesData.GetUserImageAssets(avatarId); + return records; + } + #endregion Utility + + #region UserData + public bool RequestUserAppData(ref UserAppData prop, ref string result) + { + return ProfilesData.GetUserAppData(ref prop, ref result); + } + + public bool SetUserAppData(UserAppData prop, ref string result) + { + return true; + } + #endregion UserData + } +} + diff --git a/OpenSim/Services/UserProfilesService/UserProfilesServiceBase.cs b/OpenSim/Services/UserProfilesService/UserProfilesServiceBase.cs new file mode 100644 index 0000000..c31578f --- /dev/null +++ b/OpenSim/Services/UserProfilesService/UserProfilesServiceBase.cs @@ -0,0 +1,87 @@ +/* + * 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 OpenSimulator 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.Reflection; +using Nini.Config; +using log4net; +using OpenSim.Services.Base; +using OpenSim.Data; + +namespace OpenSim.Services.ProfilesService +{ + public class UserProfilesServiceBase: ServiceBase + { + static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + public IProfilesData ProfilesData; + + public string ConfigName + { + get; private set; + } + + public UserProfilesServiceBase(IConfigSource config, string configName): + base(config) + { + if(string.IsNullOrEmpty(configName)) + { + m_log.WarnFormat("[PROFILES SERVICE]: Configuration section not given!"); + return; + } + + string dllName = String.Empty; + string connString = null; + string realm = String.Empty; + + IConfig dbConfig = config.Configs["DatabaseService"]; + if (dbConfig != null) + { + if (dllName == String.Empty) + dllName = dbConfig.GetString("StorageProvider", String.Empty); + if (string.IsNullOrEmpty(connString)) + connString = dbConfig.GetString("ConnectionString", String.Empty); + } + + IConfig ProfilesConfig = config.Configs[configName]; + if (ProfilesConfig != null) + { + dllName = ProfilesConfig.GetString("StorageProvider", dllName); + connString = ProfilesConfig.GetString("ConnectionString", connString); + realm = ProfilesConfig.GetString("Realm", realm); + } + + ProfilesData = LoadPlugin(dllName, new Object[] { connString }); + if (ProfilesData == null) + throw new Exception("Could not find a storage interface in the given module"); + + } + } +} + -- cgit v1.1