From 4c83b5e719ad288b1250fbed3f74698fa34eff21 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 7 May 2013 00:31:11 +0100 Subject: [PATCH 1/9] Step one of estate settings sharing - port the Avination Estate module (complete module) as changes are too extensive to apply manually --- .../EntityTransfer/EntityTransferModule.cs | 13 ++++- .../EntityTransfer/HGEntityTransferModule.cs | 21 ++++--- .../World/Estate/EstateManagementModule.cs | 57 ++++++++++++++----- .../Interfaces/IEntityTransferModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 5 +- 5 files changed, 71 insertions(+), 27 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index ca0cef1ea8..eac0da7ff7 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -243,7 +243,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void OnNewClient(IClientAPI client) { - client.OnTeleportHomeRequest += TeleportHome; + client.OnTeleportHomeRequest += TriggerTeleportHome; client.OnTeleportLandmarkRequest += RequestTeleportLandmark; if (!DisableInterRegionTeleportCancellation) @@ -1071,7 +1071,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #region Teleport Home - public virtual void TeleportHome(UUID id, IClientAPI client) + public virtual void TriggerTeleportHome(UUID id, IClientAPI client) + { + TeleportHome(id, client); + } + + public virtual bool TeleportHome(UUID id, IClientAPI client) { m_log.DebugFormat( "[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.Name, client.AgentId); @@ -1086,7 +1091,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // can't find the Home region: Tell viewer and abort client.SendTeleportFailed("Your home region could not be found."); - return; + return false; } m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Home region of {0} is {1} ({2}-{3})", @@ -1096,6 +1101,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer ((Scene)(client.Scene)).RequestTeleportLocation( client, regionInfo.RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome)); + return true; } else { @@ -1103,6 +1109,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer "[ENTITY TRANSFER MODULE]: No grid user information found for {0} {1}. Cannot send home.", client.Name, client.AgentId); } + return false; } #endregion diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 33ea063600..02ed1a08e3 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -184,7 +184,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected override void OnNewClient(IClientAPI client) { - client.OnTeleportHomeRequest += TeleportHome; + client.OnTeleportHomeRequest += TriggerTeleportHome; client.OnTeleportLandmarkRequest += RequestTeleportLandmark; client.OnConnectionClosed += new Action(OnConnectionClosed); } @@ -409,7 +409,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // return base.UpdateAgent(reg, finalDestination, agentData, sp); //} - public override void TeleportHome(UUID id, IClientAPI client) + public virtual void TriggerTeleportHome(UUID id, IClientAPI client) + { + TeleportHome(id, client); + } + + public override bool TeleportHome(UUID id, IClientAPI client) { m_log.DebugFormat( "[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.Name, client.AgentId); @@ -420,8 +425,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // local grid user m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local"); - base.TeleportHome(id, client); - return; + return base.TeleportHome(id, client); } // Foreign user wants to go home @@ -431,7 +435,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { client.SendTeleportFailed("Your information has been lost"); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Unable to locate agent's gateway information"); - return; + return false; } IUserAgentService userAgentService = new UserAgentServiceConnector(aCircuit.ServiceURLs["HomeURI"].ToString()); @@ -441,7 +445,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { client.SendTeleportFailed("Your home region could not be found"); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent's home region not found"); - return; + return false; } ScenePresence sp = ((Scene)(client.Scene)).GetScenePresence(client.AgentId); @@ -449,7 +453,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { client.SendTeleportFailed("Internal error"); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent not found in the scene where it is supposed to be"); - return; + return false; } GridRegion homeGatekeeper = MakeRegion(aCircuit); @@ -460,6 +464,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer DoTeleport( sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome)); + return true; } /// @@ -586,4 +591,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return region; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 60f67396db..91f6501a32 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -32,6 +32,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Security; +using System.Timers; using log4net; using Mono.Addins; using Nini.Config; @@ -48,6 +49,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Timer m_regionChangeTimer = new Timer(); public Scene Scene { get; private set; } public IUserManagement UserManager { get; private set; } @@ -65,6 +67,8 @@ namespace OpenSim.Region.CoreModules.World.Estate public event ChangeDelegate OnEstateInfoChange; public event MessageDelegate OnEstateMessage; + private int m_delayCount = 0; + #region Region Module interface public string Name { get { return "EstateManagementModule"; } } @@ -114,6 +118,12 @@ namespace OpenSim.Region.CoreModules.World.Estate #region Packet Data Responders + private void clientSendDetailedEstateData(IClientAPI remote_client, UUID invoice) + { + sendDetailedEstateData(remote_client, invoice); + sendEstateLists(remote_client, invoice); + } + private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice) { uint sun = 0; @@ -136,7 +146,10 @@ namespace OpenSim.Region.CoreModules.World.Estate (uint) Scene.RegionInfo.RegionSettings.CovenantChangedDateTime, Scene.RegionInfo.EstateSettings.AbuseEmail, estateOwner); + } + private void sendEstateLists(IClientAPI remote_client, UUID invoice) + { remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.EstateManagers, Scene.RegionInfo.EstateSettings.EstateManagers, @@ -330,7 +343,7 @@ namespace OpenSim.Region.CoreModules.World.Estate timeInSeconds -= 15; } - restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true); + restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), false); m_log.InfoFormat( "User {0} requested restart of region {1} in {2} seconds", @@ -546,7 +559,11 @@ namespace OpenSim.Region.CoreModules.World.Estate { if (!s.IsChildAgent) { - Scene.TeleportClientHome(user, s.ControllingClient); + if (!Scene.TeleportClientHome(user, s.ControllingClient)) + { + s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out."); + s.ControllingClient.Close(); + } } } @@ -555,7 +572,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { remote_client.SendAlertMessage("User is already on the region ban list"); } - //m_scene.RegionInfo.regionBanlist.Add(Manager(user); + //Scene.RegionInfo.regionBanlist.Add(Manager(user); remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID); } else @@ -611,7 +628,7 @@ namespace OpenSim.Region.CoreModules.World.Estate remote_client.SendAlertMessage("User is not on the region ban list"); } - //m_scene.RegionInfo.regionBanlist.Add(Manager(user); + //Scene.RegionInfo.regionBanlist.Add(Manager(user); remote_client.SendBannedUserList(invoice, Scene.RegionInfo.EstateSettings.EstateBans, Scene.RegionInfo.EstateSettings.EstateID); } else @@ -777,7 +794,11 @@ namespace OpenSim.Region.CoreModules.World.Estate ScenePresence s = Scene.GetScenePresence(prey); if (s != null) { - Scene.TeleportClientHome(prey, s.ControllingClient); + if (!Scene.TeleportClientHome(prey, s.ControllingClient)) + { + s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); + s.ControllingClient.Close(); + } } } } @@ -795,7 +816,13 @@ namespace OpenSim.Region.CoreModules.World.Estate // Also make sure they are actually in the region ScenePresence p; if(Scene.TryGetScenePresence(client.AgentId, out p)) - Scene.TeleportClientHome(p.UUID, p.ControllingClient); + { + if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient)) + { + p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); + p.ControllingClient.Close(); + } + } } }); } @@ -1170,7 +1197,7 @@ namespace OpenSim.Region.CoreModules.World.Estate private void EventManager_OnNewClient(IClientAPI client) { - client.OnDetailedEstateDataRequest += sendDetailedEstateData; + client.OnDetailedEstateDataRequest += clientSendDetailedEstateData; client.OnSetEstateFlagsRequest += estateSetRegionInfoHandler; // client.OnSetEstateTerrainBaseTexture += setEstateTerrainBaseTexture; client.OnSetEstateTerrainDetailTexture += setEstateTerrainBaseTexture; @@ -1218,8 +1245,6 @@ namespace OpenSim.Region.CoreModules.World.Estate flags |= RegionFlags.NoFly; if (Scene.RegionInfo.RegionSettings.RestrictPushing) flags |= RegionFlags.RestrictPushObject; - if (Scene.RegionInfo.RegionSettings.AllowLandJoinDivide) - flags |= RegionFlags.AllowParcelChanges; if (Scene.RegionInfo.RegionSettings.BlockShowInSearch) flags |= RegionFlags.BlockParcelSearch; @@ -1229,11 +1254,11 @@ namespace OpenSim.Region.CoreModules.World.Estate flags |= RegionFlags.Sandbox; if (Scene.RegionInfo.EstateSettings.AllowVoice) flags |= RegionFlags.AllowVoice; + if (Scene.RegionInfo.EstateSettings.BlockDwell) + flags |= RegionFlags.BlockDwell; + if (Scene.RegionInfo.EstateSettings.ResetHomeOnTeleport) + flags |= RegionFlags.ResetHomeOnTeleport; - // Fudge these to always on, so the menu options activate - // - flags |= RegionFlags.AllowLandmark; - flags |= RegionFlags.AllowSetHome; // TODO: SkipUpdateInterestList @@ -1293,6 +1318,12 @@ namespace OpenSim.Region.CoreModules.World.Estate } public void TriggerRegionInfoChange() + { + m_regionChangeTimer.Stop(); + m_regionChangeTimer.Start(); + } + + protected void RaiseRegionInfoChange(object sender, ElapsedEventArgs e) { ChangeDelegate change = OnRegionInfoChange; diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 69be83eb41..1c43a25e31 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -72,7 +72,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// /// - void TeleportHome(UUID id, IClientAPI client); + bool TeleportHome(UUID id, IClientAPI client); /// /// Show whether the given agent is being teleported. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 8fe2d72bdc..2aba2dda4e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3230,17 +3230,18 @@ namespace OpenSim.Region.Framework.Scenes /// /// The avatar's Unique ID /// The IClientAPI for the client - public virtual void TeleportClientHome(UUID agentId, IClientAPI client) + public virtual bool TeleportClientHome(UUID agentId, IClientAPI client) { if (EntityTransferModule != null) { - EntityTransferModule.TeleportHome(agentId, client); + return EntityTransferModule.TeleportHome(agentId, client); } else { m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); client.SendTeleportFailed("Unable to perform teleports on this simulator."); } + return false; } /// From 5d5edde4290030345bc25841a25d23552e533972 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 7 May 2013 00:37:45 +0100 Subject: [PATCH 2/9] Step 2: commit the IEstateModuleInterface changes needed --- OpenSim/Region/Framework/Interfaces/IEstateModule.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index 1983984e1c..d49b24ec0d 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs @@ -40,11 +40,12 @@ namespace OpenSim.Region.Framework.Interfaces uint GetRegionFlags(); bool IsManager(UUID avatarID); - + /// /// Tell all clients about the current state of the region (terrain textures, water height, etc.). /// void sendRegionHandshakeToAll(); + void TriggerEstateInfoChange(); /// /// Fires the OnRegionInfoChange event. From 1c6b8293d7b9e312c5b1fb544a1de7fd3b145670 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 7 May 2013 00:52:40 +0100 Subject: [PATCH 3/9] Step 3: Commit the Avination XEstate estate comms handler This adds estate-wide Teleport Home and Teleport All User Home as well --- .../World/Estate/XEstateConnector.cs | 215 +++++++++++++ .../CoreModules/World/Estate/XEstateModule.cs | 254 +++++++++++++++ .../World/Estate/XEstateRequestHandler.cs | 298 ++++++++++++++++++ 3 files changed, 767 insertions(+) create mode 100644 OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs create mode 100644 OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs create mode 100644 OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs new file mode 100644 index 0000000000..948c8934a9 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs @@ -0,0 +1,215 @@ +/* + * 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 OpenSim.Services.Interfaces; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using OpenSim.Server.Base; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; + +using OpenMetaverse; +using log4net; + +namespace OpenSim.Region.CoreModules.World.Estate +{ + public class EstateConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected XEstateModule m_EstateModule; + + public EstateConnector(XEstateModule module) + { + m_EstateModule = module; + } + + public void SendTeleportHomeOneUser(uint EstateID, UUID PreyID) + { + Dictionary sendData = new Dictionary(); + sendData["METHOD"] = "teleport_home_one_user"; + + sendData["EstateID"] = EstateID.ToString(); + sendData["PreyID"] = PreyID.ToString(); + + SendToEstate(EstateID, sendData); + } + + public void SendTeleportHomeAllUsers(uint EstateID) + { + Dictionary sendData = new Dictionary(); + sendData["METHOD"] = "teleport_home_all_users"; + + sendData["EstateID"] = EstateID.ToString(); + + SendToEstate(EstateID, sendData); + } + + public bool SendUpdateCovenant(uint EstateID, UUID CovenantID) + { + Dictionary sendData = new Dictionary(); + sendData["METHOD"] = "update_covenant"; + + sendData["CovenantID"] = CovenantID.ToString(); + sendData["EstateID"] = EstateID.ToString(); + + // Handle local regions locally + // + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == EstateID) + s.RegionInfo.RegionSettings.Covenant = CovenantID; +// s.ReloadEstateData(); + } + + SendToEstate(EstateID, sendData); + + return true; + } + + public bool SendUpdateEstate(uint EstateID) + { + Dictionary sendData = new Dictionary(); + sendData["METHOD"] = "update_estate"; + + sendData["EstateID"] = EstateID.ToString(); + + // Handle local regions locally + // + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == EstateID) + s.ReloadEstateData(); + } + + SendToEstate(EstateID, sendData); + + return true; + } + + public void SendEstateMessage(uint EstateID, UUID FromID, string FromName, string Message) + { + Dictionary sendData = new Dictionary(); + sendData["METHOD"] = "estate_message"; + + sendData["EstateID"] = EstateID.ToString(); + sendData["FromID"] = FromID.ToString(); + sendData["FromName"] = FromName; + sendData["Message"] = Message; + + SendToEstate(EstateID, sendData); + } + + private void SendToEstate(uint EstateID, Dictionary sendData) + { + List regions = m_EstateModule.Scenes[0].GetEstateRegions((int)EstateID); + + UUID ScopeID = UUID.Zero; + + // Handle local regions locally + // + foreach (Scene s in m_EstateModule.Scenes) + { + if (regions.Contains(s.RegionInfo.RegionID)) + { + // All regions in one estate are in the same scope. + // Use that scope. + // + ScopeID = s.RegionInfo.ScopeID; + regions.Remove(s.RegionInfo.RegionID); + } + } + + // Our own region should always be in the above list. + // In a standalone this would not be true. But then, + // Scope ID is not relevat there. Use first scope. + // + if (ScopeID == UUID.Zero) + ScopeID = m_EstateModule.Scenes[0].RegionInfo.ScopeID; + + // Don't send to the same instance twice + // + List done = new List(); + + // Send to remote regions + // + foreach (UUID regionID in regions) + { + GridRegion region = m_EstateModule.Scenes[0].GridService.GetRegionByUUID(ScopeID, regionID); + if (region != null) + { + string url = "http://" + region.ExternalHostName + ":" + region.HttpPort; + if (done.Contains(url)) + continue; + + Call(region, sendData); + done.Add(url); + } + } + } + + private bool Call(GridRegion region, Dictionary sendData) + { + string reqString = ServerUtils.BuildQueryString(sendData); + // m_log.DebugFormat("[XESTATE CONNECTOR]: queryString = {0}", reqString); + try + { + string url = "http://" + region.ExternalHostName + ":" + region.HttpPort; + string reply = SynchronousRestFormsRequester.MakeRequest("POST", + url + "/estate", + reqString); + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData.ContainsKey("RESULT")) + { + if (replyData["RESULT"].ToString().ToLower() == "true") + return true; + else + return false; + } + else + m_log.DebugFormat("[XESTATE CONNECTOR]: reply data does not contain result field"); + + } + else + m_log.DebugFormat("[XESTATE CONNECTOR]: received empty reply"); + } + catch (Exception e) + { + m_log.DebugFormat("[XESTATE CONNECTOR]: Exception when contacting remote sim: {0}", e.Message); + } + + return false; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs new file mode 100644 index 0000000000..1f099c61ad --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs @@ -0,0 +1,254 @@ +/* + * 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 log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Server.Base; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using Mono.Addins; + +namespace OpenSim.Region.CoreModules.World.Estate +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XEstate")] + public class XEstateModule : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected List m_Scenes = new List(); + protected bool m_InInfoUpdate = false; + + public bool InInfoUpdate + { + get { return m_InInfoUpdate; } + set { m_InInfoUpdate = value; } + } + + public List Scenes + { + get { return m_Scenes; } + } + + protected EstateConnector m_EstateConnector; + + public void Initialise(IConfigSource config) + { + int port = 0; + + IConfig estateConfig = config.Configs["Estate"]; + if (estateConfig != null) + { + port = estateConfig.GetInt("Port", 0); + } + + m_EstateConnector = new EstateConnector(this); + + // Instantiate the request handler + IHttpServer server = MainServer.GetHttpServer((uint)port); + server.AddStreamHandler(new EstateRequestHandler(this)); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public void AddRegion(Scene scene) + { + m_Scenes.Add(scene); + + scene.EventManager.OnNewClient += OnNewClient; + } + + public void RegionLoaded(Scene scene) + { + IEstateModule em = scene.RequestModuleInterface(); + + em.OnRegionInfoChange += OnRegionInfoChange; + em.OnEstateInfoChange += OnEstateInfoChange; + em.OnEstateMessage += OnEstateMessage; + } + + public void RemoveRegion(Scene scene) + { + scene.EventManager.OnNewClient -= OnNewClient; + + m_Scenes.Remove(scene); + } + + public string Name + { + get { return "EstateModule"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + private Scene FindScene(UUID RegionID) + { + foreach (Scene s in Scenes) + { + if (s.RegionInfo.RegionID == RegionID) + return s; + } + + return null; + } + + private void OnRegionInfoChange(UUID RegionID) + { + Scene s = FindScene(RegionID); + if (s == null) + return; + + if (!m_InInfoUpdate) + m_EstateConnector.SendUpdateCovenant(s.RegionInfo.EstateSettings.EstateID, s.RegionInfo.RegionSettings.Covenant); + } + + private void OnEstateInfoChange(UUID RegionID) + { + Scene s = FindScene(RegionID); + if (s == null) + return; + + if (!m_InInfoUpdate) + m_EstateConnector.SendUpdateEstate(s.RegionInfo.EstateSettings.EstateID); + } + + private void OnEstateMessage(UUID RegionID, UUID FromID, string FromName, string Message) + { + Scene senderScenes = FindScene(RegionID); + if (senderScenes == null) + return; + + uint estateID = senderScenes.RegionInfo.EstateSettings.EstateID; + + foreach (Scene s in Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == estateID) + { + IDialogModule dm = s.RequestModuleInterface(); + + if (dm != null) + { + dm.SendNotificationToUsersInRegion(FromID, FromName, + Message); + } + } + } + if (!m_InInfoUpdate) + m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message); + } + + private void OnNewClient(IClientAPI client) + { + client.OnEstateTeleportOneUserHomeRequest += OnEstateTeleportOneUserHomeRequest; + client.OnEstateTeleportAllUsersHomeRequest += OnEstateTeleportAllUsersHomeRequest; + + } + + private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey) + { + if (prey == UUID.Zero) + return; + + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)client.Scene; + + uint estateID = scene.RegionInfo.EstateSettings.EstateID; + + if (!scene.Permissions.CanIssueEstateCommand(client.AgentId, false)) + return; + + foreach (Scene s in Scenes) + { + if (s == scene) + continue; // Already handles by estate module + if (s.RegionInfo.EstateSettings.EstateID != estateID) + continue; + + ScenePresence p = scene.GetScenePresence(prey); + if (p != null && !p.IsChildAgent) + { + p.ControllingClient.SendTeleportStart(16); + scene.TeleportClientHome(prey, p.ControllingClient); + } + } + + m_EstateConnector.SendTeleportHomeOneUser(estateID, prey); + } + + private void OnEstateTeleportAllUsersHomeRequest(IClientAPI client, UUID invoice, UUID senderID) + { + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)client.Scene; + + uint estateID = scene.RegionInfo.EstateSettings.EstateID; + + if (!scene.Permissions.CanIssueEstateCommand(client.AgentId, false)) + return; + + foreach (Scene s in Scenes) + { + if (s == scene) + continue; // Already handles by estate module + if (s.RegionInfo.EstateSettings.EstateID != estateID) + continue; + + scene.ForEachScenePresence(delegate(ScenePresence p) { + if (p != null && !p.IsChildAgent) + { + p.ControllingClient.SendTeleportStart(16); + scene.TeleportClientHome(p.ControllingClient.AgentId, p.ControllingClient); + } + }); + } + + m_EstateConnector.SendTeleportHomeAllUsers(estateID); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs new file mode 100644 index 0000000000..eb74cdab76 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs @@ -0,0 +1,298 @@ +/* + * 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.IO; +using System.Reflection; +using System.Xml; + +using OpenSim.Framework; +using OpenSim.Server.Base; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; + +using OpenMetaverse; +using log4net; + +namespace OpenSim.Region.CoreModules.World.Estate +{ + public class EstateRequestHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected XEstateModule m_EstateModule; + protected Object m_RequestLock = new Object(); + + public EstateRequestHandler(XEstateModule fmodule) + : base("POST", "/estate") + { + m_EstateModule = fmodule; + } + + public override byte[] Handle(string path, Stream requestData, + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + m_log.DebugFormat("[XESTATE HANDLER]: query String: {0}", body); + + try + { + lock (m_RequestLock) + { + Dictionary request = + ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("METHOD")) + return FailureResult(); + + string method = request["METHOD"].ToString(); + request.Remove("METHOD"); + + try + { + m_EstateModule.InInfoUpdate = false; + + switch (method) + { + case "update_covenant": + return UpdateCovenant(request); + case "update_estate": + return UpdateEstate(request); + case "estate_message": + return EstateMessage(request); + case "teleport_home_one_user": + return TeleportHomeOneUser(request); + case "teleport_home_all_users": + return TeleportHomeAllUsers(request); + } + } + finally + { + m_EstateModule.InInfoUpdate = false; + } + } + } + catch (Exception e) + { + m_log.Debug("[XESTATE]: Exception {0}" + e.ToString()); + } + + return FailureResult(); + } + + byte[] TeleportHomeAllUsers(Dictionary request) + { + UUID PreyID = UUID.Zero; + int EstateID = 0; + + if (!request.ContainsKey("EstateID")) + return FailureResult(); + + if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID)) + return FailureResult(); + + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == EstateID) + { + s.ForEachScenePresence(delegate(ScenePresence p) { + if (p != null && !p.IsChildAgent) + { + p.ControllingClient.SendTeleportStart(16); + s.TeleportClientHome(p.ControllingClient.AgentId, p.ControllingClient); + } + }); + } + } + + return SuccessResult(); + } + + byte[] TeleportHomeOneUser(Dictionary request) + { + UUID PreyID = UUID.Zero; + int EstateID = 0; + + if (!request.ContainsKey("PreyID") || + !request.ContainsKey("EstateID")) + { + return FailureResult(); + } + + if (!UUID.TryParse(request["PreyID"].ToString(), out PreyID)) + return FailureResult(); + + if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID)) + return FailureResult(); + + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == EstateID) + { + ScenePresence p = s.GetScenePresence(PreyID); + if (p != null && !p.IsChildAgent) + { + p.ControllingClient.SendTeleportStart(16); + s.TeleportClientHome(PreyID, p.ControllingClient); + } + } + } + + return SuccessResult(); + } + + byte[] EstateMessage(Dictionary request) + { + UUID FromID = UUID.Zero; + string FromName = String.Empty; + string Message = String.Empty; + int EstateID = 0; + + if (!request.ContainsKey("FromID") || + !request.ContainsKey("FromName") || + !request.ContainsKey("Message") || + !request.ContainsKey("EstateID")) + { + return FailureResult(); + } + + if (!UUID.TryParse(request["FromID"].ToString(), out FromID)) + return FailureResult(); + + if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID)) + return FailureResult(); + + FromName = request["FromName"].ToString(); + Message = request["Message"].ToString(); + + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == EstateID) + { + IDialogModule dm = s.RequestModuleInterface(); + + if (dm != null) + { + dm.SendNotificationToUsersInRegion(FromID, FromName, + Message); + } + } + } + + return SuccessResult(); + } + + byte[] UpdateCovenant(Dictionary request) + { + UUID CovenantID = UUID.Zero; + int EstateID = 0; + + if (!request.ContainsKey("CovenantID") || !request.ContainsKey("EstateID")) + return FailureResult(); + + if (!UUID.TryParse(request["CovenantID"].ToString(), out CovenantID)) + return FailureResult(); + + if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID)) + return FailureResult(); + + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == (uint)EstateID) + s.RegionInfo.RegionSettings.Covenant = CovenantID; + } + + return SuccessResult(); + } + + byte[] UpdateEstate(Dictionary request) + { + int EstateID = 0; + + if (!request.ContainsKey("EstateID")) + return FailureResult(); + if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID)) + return FailureResult(); + + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == (uint)EstateID) + s.ReloadEstateData(); + } + return SuccessResult(); + } + + private byte[] FailureResult() + { + return BoolResult(false); + } + + private byte[] SuccessResult() + { + return BoolResult(true); + } + + private byte[] BoolResult(bool value) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "RESULT", ""); + result.AppendChild(doc.CreateTextNode(value.ToString())); + + rootElement.AppendChild(result); + + return DocToBytes(doc); + } + + private byte[] DocToBytes(XmlDocument doc) + { + MemoryStream ms = new MemoryStream(); + XmlTextWriter xw = new XmlTextWriter(ms, null); + xw.Formatting = Formatting.Indented; + doc.WriteTo(xw); + xw.Flush(); + + return ms.ToArray(); + } + } +} From 84118c5735f49bb38ded2ccc72b1bd7d39c09010 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 6 May 2013 18:05:37 -0700 Subject: [PATCH 4/9] BulletSim: properly free references to simple convex hull shapes. Didn't loose memory since shapes are shared but did mess up usage accounting. --- .../Region/Physics/BulletSPlugin/BSShapes.cs | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index 3e4ee5a5b8..9d47657154 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -117,11 +117,11 @@ public abstract class BSShape StringBuilder buff = new StringBuilder(); if (physShapeInfo == null) { - buff.Append(",noPhys"); + buff.Append(" Date: Mon, 6 May 2013 21:10:02 -0400 Subject: [PATCH 6/9] BulletSim: Another way to create vehicle framed friction. Signed-off-by: Robert Adams --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 04ea289bd1..e93dbd7ace 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -1028,6 +1028,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); + // Friction reduces vehicle motion + Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); + linearMotorCorrectionV -= (currentVelV * frictionFactorW); + // Motor is vehicle coordinates. Rotate it to world coordinates Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; @@ -1041,9 +1045,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Add this correction to the velocity to make it faster/slower. VehicleVelocity += linearMotorVelocityW; - // Friction reduces vehicle motion - Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep) * VehicleOrientation; - VehicleVelocity -= (VehicleVelocity * frictionFactorW); + VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}", ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, From ac6dcd35fb77f118fc6c3d72cb029591306c7e99 Mon Sep 17 00:00:00 2001 From: Vegaslon Date: Mon, 6 May 2013 21:19:48 -0400 Subject: [PATCH 7/9] Bulletsim: and the rotational friction. Signed-off-by: Robert Adams --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index e93dbd7ace..c16b7d3e6a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -1339,11 +1339,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin // angularMotorContributionV.Y = 0f; // } + // Reduce any velocity by friction. + Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep); + angularMotorContributionV -= (currentAngularV * frictionFactorW); + VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; - // Reduce any velocity by friction. - Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep) * VehicleOrientation; - VehicleRotationalVelocity -= (VehicleRotationalVelocity * frictionFactorW); + VDetailLog("{0}, MoveAngular,angularTurning,angContribV={1}", ControllingPrim.LocalID, angularMotorContributionV); } From e92c05ebbdc44084326c3dcfa0a2ca0958e4b5e6 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 7 May 2013 18:01:48 -0700 Subject: [PATCH 8/9] Added AvatarPickerSearch capability handler. --- .../AvatarPickerSearchHandler.cs | 116 +++++++++++++++ OpenSim/Capabilities/LLSDAvatarPicker.cs | 51 +++++++ OpenSim/Framework/IPeople.cs | 47 ++++++ .../Linden/Caps/AvatarPickerSearchModule.cs | 140 ++++++++++++++++++ .../UserManagement/HGUserManagementModule.cs | 2 +- .../UserManagement/UserManagementModule.cs | 72 ++++----- bin/OpenSim.ini.example | 4 +- bin/OpenSimDefaults.ini | 4 + 8 files changed, 400 insertions(+), 36 deletions(-) create mode 100644 OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs create mode 100644 OpenSim/Capabilities/LLSDAvatarPicker.cs create mode 100644 OpenSim/Framework/IPeople.cs create mode 100644 OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs diff --git a/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs b/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs new file mode 100644 index 0000000000..4dca59231e --- /dev/null +++ b/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs @@ -0,0 +1,116 @@ +/* + * 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.Collections.Specialized; +using System.IO; +using System.Reflection; +using System.Web; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +//using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Capabilities.Handlers +{ + public class AvatarPickerSearchHandler : BaseStreamHandler + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IPeople m_PeopleService; + + public AvatarPickerSearchHandler(string path, IPeople peopleService, string name, string description) + : base("GET", path, name, description) + { + m_PeopleService = peopleService; + } + + public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + // Try to parse the texture ID from the request URL + NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); + string names = query.GetOne("names"); + string psize = query.GetOne("page_size"); + string pnumber = query.GetOne("page"); + + if (m_PeopleService == null) + return FailureResponse(names, (int)System.Net.HttpStatusCode.InternalServerError, httpResponse); + + if (string.IsNullOrEmpty(names) || names.Length < 3) + return FailureResponse(names, (int)System.Net.HttpStatusCode.BadRequest, httpResponse); + + m_log.DebugFormat("[AVATAR PICKER SEARCH]: search for {0}", names); + + int page_size = (string.IsNullOrEmpty(psize) ? 500 : Int32.Parse(psize)); + int page_number = (string.IsNullOrEmpty(pnumber) ? 1 : Int32.Parse(pnumber)); + + // Full content request + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK; + //httpResponse.ContentLength = ??; + httpResponse.ContentType = "application/llsd+xml"; + + List users = m_PeopleService.GetUserData(names, page_size, page_number); + + LLSDAvatarPicker osdReply = new LLSDAvatarPicker(); + osdReply.next_page_url = httpRequest.RawUrl; + foreach (UserData u in users) + osdReply.agents.Array.Add(ConvertUserData(u)); + + string reply = LLSDHelpers.SerialiseLLSDReply(osdReply); + return System.Text.Encoding.UTF8.GetBytes(reply); + } + + private LLSDPerson ConvertUserData(UserData user) + { + LLSDPerson p = new LLSDPerson(); + p.legacy_first_name = user.FirstName; + p.legacy_last_name = user.LastName; + p.display_name = user.FirstName + " " + user.LastName; + if (user.LastName.StartsWith("@")) + p.username = user.FirstName.ToLower() + user.LastName.ToLower(); + else + p.username = user.FirstName.ToLower() + "." + user.LastName.ToLower(); + p.id = user.Id; + p.is_display_name_default = false; + return p; + } + + private byte[] FailureResponse(string names, int statuscode, IOSHttpResponse httpResponse) + { + m_log.Error("[AVATAR PICKER SEARCH]: Error searching for " + names); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + return System.Text.Encoding.UTF8.GetBytes(string.Empty); + } + } +} \ No newline at end of file diff --git a/OpenSim/Capabilities/LLSDAvatarPicker.cs b/OpenSim/Capabilities/LLSDAvatarPicker.cs new file mode 100644 index 0000000000..d0b3f3a5ec --- /dev/null +++ b/OpenSim/Capabilities/LLSDAvatarPicker.cs @@ -0,0 +1,51 @@ +/* + * 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 OpenMetaverse; + +namespace OpenSim.Framework.Capabilities +{ + [OSDMap] + public class LLSDAvatarPicker + { + public string next_page_url; + // an array of LLSDPerson + public OSDArray agents = new OSDArray(); + } + + [OSDMap] + public class LLSDPerson + { + public string username; + public string display_name; + //'display_name_next_update':d"1970-01-01T00:00:00Z" + public string legacy_first_name; + public string legacy_last_name; + public UUID id; + public bool is_display_name_default; + } +} \ No newline at end of file diff --git a/OpenSim/Framework/IPeople.cs b/OpenSim/Framework/IPeople.cs new file mode 100644 index 0000000000..b88e1039e6 --- /dev/null +++ b/OpenSim/Framework/IPeople.cs @@ -0,0 +1,47 @@ +/* + * 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.Framework +{ + public class UserData + { + public UUID Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string HomeURL { get; set; } + public Dictionary ServerURLs { get; set; } + } + + public interface IPeople + { + List GetUserData(string query, int page_size, int page_number); + } +} \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs new file mode 100644 index 0000000000..d7af1f29a0 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs @@ -0,0 +1,140 @@ +/* + * 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.Specialized; +using System.Drawing; +using System.Drawing.Imaging; +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.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; +using OpenSim.Capabilities.Handlers; + +namespace OpenSim.Region.ClientStack.Linden +{ + + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AvatarPickerSearchModule")] + public class AvatarPickerSearchModule : INonSharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + private IPeople m_People; + private bool m_Enabled = false; + + private string m_URL; + + #region ISharedRegionModule Members + + public void Initialise(IConfigSource source) + { + IConfig config = source.Configs["ClientStack.LindenCaps"]; + if (config == null) + return; + + m_URL = config.GetString("Cap_AvatarPickerSearch", string.Empty); + m_log.DebugFormat("[XXX]: Cap_AvatarPickerSearch = {0}", m_URL); + // Cap doesn't exist + if (m_URL != string.Empty) + m_Enabled = true; + } + + public void AddRegion(Scene s) + { + if (!m_Enabled) + return; + + m_scene = s; + } + + public void RemoveRegion(Scene s) + { + if (!m_Enabled) + return; + + m_scene.EventManager.OnRegisterCaps -= RegisterCaps; + m_scene = null; + } + + public void RegionLoaded(Scene s) + { + if (!m_Enabled) + return; + + m_People = m_scene.RequestModuleInterface(); + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void PostInitialise() + { + } + + public void Close() { } + + public string Name { get { return "AvatarPickerSearchModule"; } } + + public Type ReplaceableInterface + { + get { return null; } + } + + #endregion + + public void RegisterCaps(UUID agentID, Caps caps) + { + UUID capID = UUID.Random(); + + if (m_URL == "localhost") + { + m_log.DebugFormat("[AVATAR PICKER SEARCH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); + caps.RegisterHandler( + "AvatarPickerSearch", + new AvatarPickerSearchHandler("/CAPS/" + capID + "/", m_People, "AvatarPickerSearch", "Search for avatars by name")); + } + else + { + // m_log.DebugFormat("[AVATAR PICKER SEARCH]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName); + caps.RegisterHandler("AvatarPickerSearch", m_URL); + } + } + + } +} diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs index 8ce20e9950..fac93e63bb 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs @@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement #endregion ISharedRegionModule - protected override void AddAdditionalUsers(UUID avatarID, string query, List users) + protected override void AddAdditionalUsers(string query, List users) { if (query.Contains("@")) // First.Last@foo.com, maybe? { diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 7b823ba8f0..6847e572fb 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -46,17 +46,8 @@ using Mono.Addins; namespace OpenSim.Region.CoreModules.Framework.UserManagement { - public class UserData - { - public UUID Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public string HomeURL { get; set; } - public Dictionary ServerURLs { get; set; } - } - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")] - public class UserManagementModule : ISharedRegionModule, IUserManagement + public class UserManagementModule : ISharedRegionModule, IUserManagement, IPeople { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -101,6 +92,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement m_Scenes.Add(scene); scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); } @@ -181,29 +173,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); - // searhc the user accounts service - List accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); - - List users = new List(); - if (accs != null) - { - foreach (UserAccount acc in accs) - { - UserData ud = new UserData(); - ud.FirstName = acc.FirstName; - ud.LastName = acc.LastName; - ud.Id = acc.PrincipalID; - users.Add(ud); - } - } - - // search the local cache - foreach (UserData data in m_UserCache.Values) - if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && - (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower()))) - users.Add(data); - - AddAdditionalUsers(avatarID, query, users); + List users = GetUserData(query, 500, 1); AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); // TODO: don't create new blocks if recycling an old packet @@ -249,12 +219,46 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement client.SendAvatarPickerReply(agent_data, data_args); } - protected virtual void AddAdditionalUsers(UUID avatarID, string query, List users) + protected virtual void AddAdditionalUsers(string query, List users) { } #endregion Event Handlers + #region IPeople + + public List GetUserData(string query, int page_size, int page_number) + { + // search the user accounts service + List accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); + + List users = new List(); + if (accs != null) + { + foreach (UserAccount acc in accs) + { + UserData ud = new UserData(); + ud.FirstName = acc.FirstName; + ud.LastName = acc.LastName; + ud.Id = acc.PrincipalID; + users.Add(ud); + } + } + + // search the local cache + foreach (UserData data in m_UserCache.Values) + if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && + (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower()))) + users.Add(data); + + AddAdditionalUsers(query, users); + + return users; + + } + + #endregion IPeople + private void CacheCreators(SceneObjectGroup sog) { //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification); diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index ce2e6008cf..5e486d4d2e 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -507,8 +507,10 @@ ;; "" -- capability enabled and served by some other server ;; ; These are enabled by default to localhost. Change if you see fit. - Cap_GetTexture = "localhost" + Cap_GetTexture = "localhost" Cap_GetMesh = "localhost" + Cap_AvatarPickerSearch = "localhost" + ; This is disabled by default. Change if you see fit. Note that ; serving this cap from the simulators may lead to poor performace. Cap_WebFetchInventoryDescendents = "" diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 28c1db27e7..7666243e2c 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -609,6 +609,10 @@ Cap_WebFetchInventoryDescendents = "" Cap_FetchInventoryDescendents2 = "localhost" Cap_FetchInventory2 = "localhost" + + ; Capability for searching for people + Cap_AvatarPickerSearch = "localhost" + [Chat] From 601aa9116348a88e8fe4d33f7dd7408ddc6fee28 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 7 May 2013 19:16:42 -0700 Subject: [PATCH 9/9] Delete "" entry for AvatarPicker cap. --- bin/OpenSimDefaults.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 7666243e2c..0e35c639a8 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -545,7 +545,6 @@ ;; in OpenSim.ini ;; Cap_AttachmentResources = "" - Cap_AvatarPickerSearch = "" Cap_ChatSessionRequest = "" Cap_CopyInventoryFromNotecard = "localhost" Cap_DispatchRegionInfo = ""