From 5573fcfa933bb9c594fb10d9b15477ab7e316b79 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 May 2011 00:10:27 +0100 Subject: [PATCH 001/186] Fix adding/removing/replacing outfits in viewer 2 To get this to work, I had to disable the dupe link check I put in a couple of commits ago. When the viewer adds wearables to an existing outfit, it first requests deletes of all the existing links before creating a new set. Since these messages are async, the creates were being received before the deletes had a chance to complete, resulting in missing current outfit links. However, the dupe check shouldn't be as important now that broken links have been fixed - it was the broken links that were causing the client to create dupes. Tested on kokua 0.1.0 WIP and SL 2.6.3. I now have no problems managing outfits on my standalone. --- .../Framework/Scenes/Scene.Inventory.cs | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 3bf2c2b61e..e242010120 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -924,9 +924,9 @@ namespace OpenSim.Region.Framework.Scenes uint callbackID, string description, string name, sbyte invType, sbyte type, UUID olditemID) { - m_log.DebugFormat( - "[AGENT INVENTORY]: Received request from {0} to create inventory item link {1} in folder {2} pointing to {3}", - remoteClient.Name, name, folderID, olditemID); +// m_log.DebugFormat( +// "[AGENT INVENTORY]: Received request from {0} to create inventory item link {1} in folder {2} pointing to {3}", +// remoteClient.Name, name, folderID, olditemID); if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) return; @@ -934,20 +934,25 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence presence; if (TryGetScenePresence(remoteClient.AgentId, out presence)) { - bool linkAlreadyExists = false; - List existingItems = InventoryService.GetFolderItems(remoteClient.AgentId, folderID); - foreach (InventoryItemBase item in existingItems) - if (item.AssetID == olditemID) - linkAlreadyExists = true; - - if (linkAlreadyExists) - { - m_log.WarnFormat( - "[AGENT INVENTORY]: Ignoring request from {0} to create item link {1} in folder {2} pointing to {3} since a link already exists", - remoteClient.Name, name, folderID, olditemID); - - return; - } + // Disabled the check for duplicate links. + // + // When outfits are being adjusted, the viewer rapidly sends delete link messages followed by + // create links. However, since these are handled asynchronously, the deletes do not complete before + // the creates are handled. Therefore, we cannot enforce a duplicate link check. +// InventoryItemBase existingLink = null; +// List existingItems = InventoryService.GetFolderItems(remoteClient.AgentId, folderID); +// foreach (InventoryItemBase item in existingItems) +// if (item.AssetID == olditemID) +// existingLink = item; +// +// if (existingLink != null) +// { +// m_log.WarnFormat( +// "[AGENT INVENTORY]: Ignoring request from {0} to create item link {1} in folder {2} pointing to {3} since a link named {4} with id {5} already exists", +// remoteClient.Name, name, folderID, olditemID, existingLink.Name, existingLink.ID); +// +// return; +// } AssetBase asset = new AssetBase(); asset.FullID = olditemID; @@ -975,7 +980,11 @@ namespace OpenSim.Region.Framework.Scenes /// private void RemoveInventoryItem(IClientAPI remoteClient, List itemIDs) { - //m_log.Debug("[SCENE INVENTORY]: user " + remoteClient.AgentId); +// m_log.DebugFormat( +// "[AGENT INVENTORY]: Removing inventory items {0} for {1}", +// string.Join(",", itemIDs.ConvertAll(uuid => uuid.ToString()).ToArray()), +// remoteClient.Name); + InventoryService.DeleteItems(remoteClient.AgentId, itemIDs); } From 7a54638b57d7ce4b98cd267ee97b650bdac27b92 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Sat, 7 May 2011 11:19:01 +0900 Subject: [PATCH 002/186] Swapped the two restart command descriptions each other --- OpenSim/Region/CoreModules/World/Region/RestartModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs index e983239b4a..0f37dddc86 100644 --- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs +++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs @@ -70,14 +70,14 @@ namespace OpenSim.Region.CoreModules.World.Region false, "region restart bluebox", "region restart bluebox +", "Schedule a region restart", - "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a transient notice. If multiple deltas are given then a notice is sent when we reach each delta.", + "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a dismissable bluebox notice. If multiple deltas are given then a notice is sent when we reach each delta.", HandleRegionRestart); MainConsole.Instance.Commands.AddCommand("RestartModule", false, "region restart notice", "region restart notice +", "Schedule a region restart", - "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a dismissable bluebox notice. If multiple deltas are given then a notice is sent when we reach each delta.", + "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a transient notice. If multiple deltas are given then a notice is sent when we reach each delta.", HandleRegionRestart); MainConsole.Instance.Commands.AddCommand("RestartModule", From cb6cd3714eb051af23e45c1f4d792d12feb1f4b8 Mon Sep 17 00:00:00 2001 From: SignpostMarv Martin Date: Fri, 13 May 2011 09:58:29 +0100 Subject: [PATCH 003/186] The get_grid_info REST call now encodes XML Entities --- OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs b/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs index cdab49ed6b..0da9fc112a 100644 --- a/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs +++ b/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs @@ -30,6 +30,7 @@ using System.Collections; using System.IO; using System.Net; using System.Reflection; +using System.Security; using System.Text; using log4net; using Nini.Config; @@ -143,7 +144,7 @@ namespace OpenSim.Server.Handlers.Grid sb.Append("\n"); foreach (string k in _info.Keys) { - sb.AppendFormat("<{0}>{1}\n", k, _info[k]); + sb.AppendFormat("<{0}>{1}\n", k, SecurityElement.Escape(_info[k].ToString())); } sb.Append("\n"); From 64d868fb64329b1c961dc8f520c71789bc146609 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Thu, 12 May 2011 14:42:28 +0300 Subject: [PATCH 004/186] When loading an OAR that doesn't have parcels, create a default parcel --- .../World/Archiver/ArchiveReadRequest.cs | 11 +++++++---- .../World/Archiver/Tests/ArchiverTests.cs | 2 ++ .../World/Land/LandManagementModule.cs | 19 +++++++++++-------- OpenSim/Tests/Common/Mock/TestLandChannel.cs | 13 +++++++++++-- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 82bef48c8c..64616365f4 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -347,12 +347,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver landData.Add(parcel); } - - if (!m_merge) - m_scene.LandChannel.Clear(false); + + if (!m_merge) + { + bool setupDefaultParcel = (landData.Count == 0); + m_scene.LandChannel.Clear(setupDefaultParcel); + } m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData); - m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); + m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); } /// diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 2307c8e585..729e9f78bd 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -313,6 +313,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null"); Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); + Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); + // Temporary Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); } diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index bfab7b88e4..2eac79d31e 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -668,14 +668,14 @@ namespace OpenSim.Region.CoreModules.World.Land //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); } - + m_landList.Clear(); + + ResetSimLandObjects(); + + if (setupDefaultParcel) + CreateDefaultParcel(); } - - ResetSimLandObjects(); - - if (setupDefaultParcel) - CreateDefaultParcel(); } private void performFinalLandJoin(ILandObject master, ILandObject slave) @@ -1391,8 +1391,11 @@ namespace OpenSim.Region.CoreModules.World.Land public void EventManagerOnNoLandDataFromStorage() { - ResetSimLandObjects(); - CreateDefaultParcel(); + lock (m_landList) + { + ResetSimLandObjects(); + CreateDefaultParcel(); + } } #endregion diff --git a/OpenSim/Tests/Common/Mock/TestLandChannel.cs b/OpenSim/Tests/Common/Mock/TestLandChannel.cs index c3134b3bc1..0e4dfb9eee 100644 --- a/OpenSim/Tests/Common/Mock/TestLandChannel.cs +++ b/OpenSim/Tests/Common/Mock/TestLandChannel.cs @@ -40,10 +40,12 @@ namespace OpenSim.Tests.Common.Mock public class TestLandChannel : ILandChannel { private Scene m_scene; + private List m_parcels; public TestLandChannel(Scene scene) { m_scene = scene; + m_parcels = new List(); } public List ParcelsNearPoint(Vector3 position) @@ -53,12 +55,19 @@ namespace OpenSim.Tests.Common.Mock public List AllParcels() { - return new List(); + return m_parcels; } public void Clear(bool setupDefaultParcel) { - // Intentionally blank since we don't save any parcel data in the test channel + m_parcels.Clear(); + + if (setupDefaultParcel) + { + ILandObject obj = new LandObject(UUID.Zero, false, m_scene); + obj.LandData.Name = "Your Parcel"; + m_parcels.Add(obj); + } } protected ILandObject GetNoLand() From 26ce1d27d0f544ebe8fcab672c2e18401067cdd6 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 May 2011 01:07:06 +0100 Subject: [PATCH 005/186] Minor doc change to see if this provokes a good panda build --- .../Region/CoreModules/World/Land/LandManagementModule.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 2eac79d31e..63dec1516f 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -520,8 +520,12 @@ namespace OpenSim.Region.CoreModules.World.Land } } + /// + /// Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance. + /// + /// public void EventManagerOnClientMovement(ScenePresence avatar) - //Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance. + // { ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); if (over != null) @@ -534,7 +538,6 @@ namespace OpenSim.Region.CoreModules.World.Land } } - public void ClientOnParcelAccessListRequest(UUID agentID, UUID sessionID, uint flags, int sequenceID, int landLocalID, IClientAPI remote_client) { From 1d8607914170d285f15b4d48a3ae7a17f56f6aa8 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 May 2011 01:26:04 +0100 Subject: [PATCH 006/186] Correct llGetParcelMaxPrims() to use the same calculation as used elsewhere instead of the old 0.22 prims/meter squared fudge factor. Thanks to tglion for this. --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index aa28fa0ca2..bda46fbca6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9908,8 +9908,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide) { m_host.AddScriptLPS(1); - // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation - // Which probably will be irrelevent in OpenSim.... + LandData land = World.GetLandData((float)pos.x, (float)pos.y); float bonusfactor = (float)World.RegionInfo.RegionSettings.ObjectBonus; @@ -9921,16 +9920,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (sim_wide != 0) { - decimal v = land.SimwideArea * (decimal)(0.22) * (decimal)bonusfactor; + int v = (int)((land.SimwideArea / 65536.0f) * (float)World.RegionInfo.ObjectCapacity * bonusfactor); - return (int)v; + return v; } else { - decimal v = land.Area * (decimal)(0.22) * (decimal)bonusfactor; + int v = (int)((land.Area / 65536.0f) * (float)World.RegionInfo.ObjectCapacity * bonusfactor); - return (int)v; + return v; } } From bef1ffa7db3c90f08b3a855e3a5d3d5c7b114549 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 May 2011 02:34:46 +0100 Subject: [PATCH 007/186] simplify code in llGetParcelMaxPrims() to use existing code in LandObject rather than duping the algo --- .../Shared/Api/Implementation/LSL_Api.cs | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index bda46fbca6..201028337d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9909,29 +9909,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - LandData land = World.GetLandData((float)pos.x, (float)pos.y); + ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); - float bonusfactor = (float)World.RegionInfo.RegionSettings.ObjectBonus; - - if (land == null) - { + if (lo == null) return 0; - } if (sim_wide != 0) - { - int v = (int)((land.SimwideArea / 65536.0f) * (float)World.RegionInfo.ObjectCapacity * bonusfactor); - - return v; - } - + return lo.GetSimulatorMaxPrimCount(lo); else - { - int v = (int)((land.Area / 65536.0f) * (float)World.RegionInfo.ObjectCapacity * bonusfactor); - - return v; - } - + return lo.GetParcelMaxPrimCount(lo); } public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) From 340e3ccf16a59512f86f9c5d08bda3ca8179f53e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 May 2011 02:42:47 +0100 Subject: [PATCH 008/186] refactor: remove thisObject argument from ILandObject.Get*MaxPrimCount() instance methods since it didn't make sense to use anything other than the instance themselves. --- OpenSim/Framework/ILandObject.cs | 4 ++-- .../Region/CoreModules/World/Land/LandObject.cs | 15 ++++++++------- .../Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs index 5a55b02f8e..0316944072 100644 --- a/OpenSim/Framework/ILandObject.cs +++ b/OpenSim/Framework/ILandObject.cs @@ -35,8 +35,8 @@ namespace OpenSim.Framework public interface ILandObject { - int GetParcelMaxPrimCount(ILandObject thisObject); - int GetSimulatorMaxPrimCount(ILandObject thisObject); + int GetParcelMaxPrimCount(); + int GetSimulatorMaxPrimCount(); int GetPrimsFree(); LandData LandData { get; set; } diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index c2f104e370..560b862625 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.World.Land public int GetPrimsFree() { m_scene.EventManager.TriggerParcelPrimCountUpdate(); - int free = GetSimulatorMaxPrimCount(this) - m_landData.SimwidePrims; + int free = GetSimulatorMaxPrimCount() - m_landData.SimwidePrims; return free; } @@ -181,11 +181,11 @@ namespace OpenSim.Region.CoreModules.World.Land overrideSimulatorMaxPrimCount = overrideDel; } - public int GetParcelMaxPrimCount(ILandObject thisObject) + public int GetParcelMaxPrimCount() { if (overrideParcelMaxPrimCount != null) { - return overrideParcelMaxPrimCount(thisObject); + return overrideParcelMaxPrimCount(this); } else { @@ -197,11 +197,12 @@ namespace OpenSim.Region.CoreModules.World.Land return parcelMax; } } - public int GetSimulatorMaxPrimCount(ILandObject thisObject) + + public int GetSimulatorMaxPrimCount() { if (overrideSimulatorMaxPrimCount != null) { - return overrideSimulatorMaxPrimCount(thisObject); + return overrideSimulatorMaxPrimCount(this); } else { @@ -244,8 +245,8 @@ namespace OpenSim.Region.CoreModules.World.Land remote_client.SendLandProperties(seq_id, snap_selection, request_result, this, (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, - GetParcelMaxPrimCount(this), - GetSimulatorMaxPrimCount(this), regionFlags); + GetParcelMaxPrimCount(), + GetSimulatorMaxPrimCount(), regionFlags); } public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 201028337d..02402271c1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9915,9 +9915,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return 0; if (sim_wide != 0) - return lo.GetSimulatorMaxPrimCount(lo); + return lo.GetSimulatorMaxPrimCount(); else - return lo.GetParcelMaxPrimCount(lo); + return lo.GetParcelMaxPrimCount(); } public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) From e3b8d42bbc8fe0e85ece55c0a293ecd7a2b55295 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 May 2011 02:51:29 +0100 Subject: [PATCH 009/186] refactor: improve PrimLimitsModule to call ILandObject.GetSimulatorMaxPrimCount() rather than use copy/pasted code --- .../PrimLimitsModule/PrimLimitsModule.cs | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs index 471b90f0e1..c1957e2cb8 100644 --- a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs +++ b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs @@ -76,22 +76,24 @@ namespace OpenSim.Region.OptionalModules public void AddRegion(Scene scene) { - if(!m_enabled) + if (!m_enabled) { return; } scene.Permissions.OnRezObject += CanRezObject; scene.Permissions.OnObjectEntry += CanObjectEnter; scene.Permissions.OnDuplicateObject += CanDuplicateObject; + m_log.DebugFormat("[PRIM LIMITS]: Region {0} added", scene.RegionInfo.RegionName); } public void RemoveRegion(Scene scene) { - if(m_enabled) + if (m_enabled) { return; } + scene.Permissions.OnRezObject -= CanRezObject; scene.Permissions.OnObjectEntry -= CanObjectEnter; scene.Permissions.OnDuplicateObject -= CanDuplicateObject; @@ -104,13 +106,11 @@ namespace OpenSim.Region.OptionalModules private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene) { - // This may be a little long winded and can probably be optomized - int usedPrims = scene.LandChannel.GetLandObject(objectPosition.X,objectPosition.Y).PrimCounts.Total; - LandData landData = scene.LandChannel.GetLandObject(objectPosition.X,objectPosition.Y).LandData; - int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * - (float)scene.RegionInfo.ObjectCapacity * (float)scene.RegionInfo.RegionSettings.ObjectBonus); + ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); + int usedPrims = lo.PrimCounts.Total; + int simulatorCapacity = lo.GetSimulatorMaxPrimCount(); - if(objectCount + usedPrims > simulatorCapacity) + if (objectCount + usedPrims > simulatorCapacity) { m_dialogModule.SendAlertToUser(owner, "Unable to rez object because the parcel is too full"); return false; @@ -118,7 +118,7 @@ namespace OpenSim.Region.OptionalModules return true; } - //OnMoveObject + private bool CanObjectEnter(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene) { SceneObjectPart obj = scene.GetSceneObjectPart(objectID); @@ -126,11 +126,9 @@ namespace OpenSim.Region.OptionalModules int objectCount = obj.ParentGroup.PrimCount; ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y); ILandObject newParcel = scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); - - int usedPrims=newParcel.PrimCounts.Total; - LandData landData = newParcel.LandData; - int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * - (float)scene.RegionInfo.ObjectCapacity * (float)scene.RegionInfo.RegionSettings.ObjectBonus); + + int usedPrims = newParcel.PrimCounts.Total; + int simulatorCapacity = newParcel.GetSimulatorMaxPrimCount(); // The prim hasn't crossed a region boundry so we don't need to worry // about prim counts here @@ -138,36 +136,39 @@ namespace OpenSim.Region.OptionalModules { return true; } + // Prim counts are determined by the location of the root prim. if we're // moving a child prim, just let it pass if(!obj.IsRoot) { return true; } - // Add Special Case here for temporary prims + + // TODO: Add Special Case here for temporary prims if(objectCount + usedPrims > simulatorCapacity) { m_dialogModule.SendAlertToUser(obj.OwnerID, "Unable to move object because the destination parcel is too full"); return false; } + return true; } + //OnDuplicateObject private bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition) { - // This may be a little long winded and can probably be optomized - int usedPrims = scene.LandChannel.GetLandObject(objectPosition.X,objectPosition.Y).PrimCounts.Total; - LandData landData = scene.LandChannel.GetLandObject(objectPosition.X,objectPosition.Y).LandData; - int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * - (float)scene.RegionInfo.ObjectCapacity * (float)scene.RegionInfo.RegionSettings.ObjectBonus); + ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); + int usedPrims = lo.PrimCounts.Total; + int simulatorCapacity = lo.GetSimulatorMaxPrimCount(); if(objectCount + usedPrims > simulatorCapacity) { m_dialogModule.SendAlertToUser(owner, "Unable to duplicate object because the parcel is too full"); return false; } + return true; } } -} +} \ No newline at end of file From a3aa839d751b04f1898b728fc9b8bc9e65352b21 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 14 May 2011 12:56:50 -0700 Subject: [PATCH 010/186] Stop spamming Nebadon's console when assets aren't found in the asset server. --- OpenSim/Framework/WebUtil.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 27a646aad1..5628376702 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -979,8 +979,11 @@ namespace OpenSim.Framework try { - using (WebResponse resp = request.GetResponse()) + using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse()) { + if (resp.StatusCode == HttpStatusCode.NotFound) + return deserial; + if (resp.ContentLength != 0) { Stream respStream = resp.GetResponseStream(); From be6feff331a97b1e976ca52aa0012f24c837e5d6 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 14 May 2011 13:09:59 -0700 Subject: [PATCH 011/186] Also changed a couple of messages in WebUtil from Wanr/Info to Debug. --- OpenSim/Framework/WebUtil.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 5628376702..93236078b0 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -251,11 +251,11 @@ namespace OpenSim.Framework // This just dumps a warning for any operation that takes more than 100 ms int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); if (tickdiff > LongCallTime) - m_log.InfoFormat("[WEB UTIL]: osd request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing", + m_log.DebugFormat("[WEB UTIL]: osd request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing", reqnum,url,method,tickdiff,tickdata); } - m_log.WarnFormat("[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage); + m_log.DebugFormat("[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage); return ErrorResponseMap(errorMessage); } From a2f034c5546880215baae53184e591b2e4fd223f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 14 May 2011 13:36:55 -0700 Subject: [PATCH 012/186] Changed yet more Warns to Debugs. --- OpenSim/Framework/WebUtil.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 93236078b0..147a0110c0 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -967,7 +967,7 @@ namespace OpenSim.Framework } catch (Exception e) { - m_log.WarnFormat("[SynchronousRestObjectRequester]: exception in sending data to {0}: {1}", requestUrl, e); + m_log.DebugFormat("[SynchronousRestObjectRequester]: exception in sending data to {0}: {1}", requestUrl, e); return deserial; } finally @@ -992,18 +992,18 @@ namespace OpenSim.Framework respStream.Close(); } else - m_log.WarnFormat("[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}", requestUrl, verb); + m_log.DebugFormat("[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}", requestUrl, verb); } } catch (System.InvalidOperationException) { // This is what happens when there is invalid XML - m_log.WarnFormat("[SynchronousRestObjectRequester]: Invalid XML {0} {1}", requestUrl, typeof(TResponse).ToString()); + m_log.DebugFormat("[SynchronousRestObjectRequester]: Invalid XML {0} {1}", requestUrl, typeof(TResponse).ToString()); } catch (Exception e) { - m_log.WarnFormat("[SynchronousRestObjectRequester]: Exception on response from {0} {1}", requestUrl, e); + m_log.DebugFormat("[SynchronousRestObjectRequester]: Exception on response from {0} {1}", requestUrl, e); } return deserial; From 901448a8eb88eac256fd25e3b7a24ebfcceb69f1 Mon Sep 17 00:00:00 2001 From: Kim King Date: Sun, 15 May 2011 03:35:45 -0400 Subject: [PATCH 013/186] Fixup documentation for AutoBackupModule. --- .../World/AutoBackup/AutoBackupModule.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs index ce9a4481ea..d40caebbee 100644 --- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs +++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs @@ -58,12 +58,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// /// /// Config Settings Documentation. - /// At the TOP LEVEL, e.g. in OpenSim.ini, we have the following options: - /// EACH REGION, in OpenSim.ini, can have the following settings under the [AutoBackupModule] section. - /// IMPORTANT: You may optionally specify the key name as follows for a per-region key: [Region Name].[Key Name] - /// Example: My region is named Foo. - /// If I wanted to specify the "AutoBackupInterval" key just for this region, I would name my key "Foo.AutoBackupInterval", under the [AutoBackupModule] section of OpenSim.ini. - /// Instead of specifying them on a per-region basis, you can also omit the region name to specify the default setting for all regions. + /// Each configuration setting can be specified in two places: OpenSim.ini or Regions.ini. + /// If specified in Regions.ini, the settings should be within the region's section name. + /// If specified in OpenSim.ini, the settings should be within the [AutoBackupModule] section. /// Region-specific settings take precedence. /// /// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module. This setting does not support per-region basis. @@ -71,7 +68,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// AutoBackup: True/False. Default: False. If True, activate auto backup functionality. /// This is the only required option for enabling auto-backup; the other options have sane defaults. /// If False for a particular region, the auto-backup module becomes a no-op for the region, and all other AutoBackup* settings are ignored. - /// If False globally (the default), only regions that specifically override this with "FooRegion.AutoBackup = true" will get AutoBackup functionality. + /// If False globally (the default), only regions that specifically override it in Regions.ini will get AutoBackup functionality. /// AutoBackupInterval: Double, non-negative value. Default: 720 (12 hours). /// The number of minutes between each backup attempt. /// If a negative or zero value is given, it is equivalent to setting AutoBackup = False. From 4232b1a89b6647770a302a0102c9109b7d0fce28 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 17 May 2011 01:57:18 +0100 Subject: [PATCH 014/186] convert tabs to spaces --- .../OptionalModules/World/AutoBackup/AutoBackupModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs index d40caebbee..b74d6e7c7d 100644 --- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs +++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs @@ -59,8 +59,8 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// /// Config Settings Documentation. /// Each configuration setting can be specified in two places: OpenSim.ini or Regions.ini. - /// If specified in Regions.ini, the settings should be within the region's section name. - /// If specified in OpenSim.ini, the settings should be within the [AutoBackupModule] section. + /// If specified in Regions.ini, the settings should be within the region's section name. + /// If specified in OpenSim.ini, the settings should be within the [AutoBackupModule] section. /// Region-specific settings take precedence. /// /// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module. This setting does not support per-region basis. From 784f70f70405aa5b163865a01637fe6132dd1bc5 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 17 May 2011 02:25:05 +0100 Subject: [PATCH 015/186] don't throw a null reference if an inventory link target doesn't exist when we're inspecting in order to send the required inventory folders --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index e242010120..7b88f4f439 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1404,7 +1404,10 @@ namespace OpenSim.Region.Framework.Scenes if (item.AssetType == (int)AssetType.Link) { InventoryItemBase linkedItem = InventoryService.GetItem(new InventoryItemBase(item.AssetID)); - linkedItemFolderIdsToSend.Add(linkedItem.Folder); + + // Take care of genuinely broken links where the target doesn't exist + if (linkedItem != null) + linkedItemFolderIdsToSend.Add(linkedItem.Folder); } } From 491279f99afc65860d44765ee7829c7dd5e4e38e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 17 May 2011 21:49:38 +0100 Subject: [PATCH 016/186] Allow item links to be deleted even when other deletes and purges are disabled. If these links are not deleted, then they will build up in the player's inventory until they can no longer log in. Accidental deletion of links due to bugs or other causes is potentially inconvenient but on a par with items being accidentally moved. When a link is deleted, the target of the link is never touched. This is a general solution that accounts for the use of links anywhere in the user's inventory. --- OpenSim/Data/IXInventoryData.cs | 29 +++++++++++++++ .../Data/MSSQL/MSSQLGenericTableHandler.cs | 35 ++++++++++++------- OpenSim/Data/MSSQL/MSSQLXInventoryData.cs | 10 ++++++ .../Data/MySQL/MySQLGenericTableHandler.cs | 27 ++++++++++---- OpenSim/Data/MySQL/MySQLXInventoryData.cs | 10 ++++++ .../Data/SQLite/SQLiteGenericTableHandler.cs | 28 +++++++++++---- OpenSim/Data/SQLite/SQLiteXInventoryData.cs | 10 ++++++ .../InventoryService/XInventoryService.cs | 30 ++++++++++++---- 8 files changed, 149 insertions(+), 30 deletions(-) diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs index d85a7efb8f..85a5c08d37 100644 --- a/OpenSim/Data/IXInventoryData.cs +++ b/OpenSim/Data/IXInventoryData.cs @@ -74,9 +74,38 @@ namespace OpenSim.Data bool StoreFolder(XInventoryFolder folder); bool StoreItem(XInventoryItem item); + /// + /// Delete folders where field == val + /// + /// + /// + /// true if the delete was successful, false if it was not bool DeleteFolders(string field, string val); + + /// + /// Delete folders where field1 == val1, field2 == val2... + /// + /// + /// + /// true if the delete was successful, false if it was not + bool DeleteFolders(string[] fields, string[] vals); + + /// + /// Delete items where field == val + /// + /// + /// + /// true if the delete was successful, false if it was not bool DeleteItems(string field, string val); + /// + /// Delete items where field1 == val1, field2 == val2... + /// + /// + /// + /// true if the delete was successful, false if it was not + bool DeleteItems(string[] fields, string[] vals); + bool MoveItem(string id, string newParent); XInventoryItem[] GetActiveGestures(UUID principalID); int GetAssetPermissions(UUID principalID, UUID assetID); diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs index f5492b3050..317afac493 100644 --- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs +++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs @@ -335,24 +335,35 @@ namespace OpenSim.Data.MSSQL } } - public virtual bool Delete(string field, string val) + public virtual bool Delete(string field, string key) { + return Delete(new string[] { field }, new string[] { key }); + } + + public virtual bool Delete(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return false; + + List terms = new List(); + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) { - string deleteCommand = String.Format("DELETE FROM {0} WHERE [{1}] = @{1}", m_Realm, field); - cmd.CommandText = deleteCommand; - - cmd.Parameters.Add(m_database.CreateParameter(field, val)); - cmd.Connection = conn; - conn.Open(); - - if (cmd.ExecuteNonQuery() > 0) + for (int i = 0; i < fields.Length; i++) { - //m_log.Warn("[MSSQLGenericTable]: " + deleteCommand); - return true; + cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i])); + terms.Add("[" + fields[i] + "] = @" + fields[i]); } - return false; + + string where = String.Join(" AND ", terms.ToArray()); + + string query = String.Format("DELETE * FROM {0} WHERE {1}", m_Realm, where); + + cmd.Connection = conn; + cmd.CommandText = query; + conn.Open(); + return cmd.ExecuteNonQuery() > 0; } } } diff --git a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs index 5bc4fe41e5..01689a43e6 100644 --- a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs +++ b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs @@ -79,11 +79,21 @@ namespace OpenSim.Data.MSSQL return m_Folders.Delete(field, val); } + public bool DeleteFolders(string[] fields, string[] vals) + { + return m_Folders.Delete(fields, vals); + } + public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } + public bool DeleteItems(string[] fields, string[] vals) + { + return m_Items.Delete(fields, vals); + } + public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index cfffbd8739..754cf725f0 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -264,18 +264,33 @@ namespace OpenSim.Data.MySQL } } - public virtual bool Delete(string field, string val) + public virtual bool Delete(string field, string key) { + return Delete(new string[] { field }, new string[] { key }); + } + + public virtual bool Delete(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return false; + + List terms = new List(); + using (MySqlCommand cmd = new MySqlCommand()) { + for (int i = 0 ; i < fields.Length ; i++) + { + cmd.Parameters.AddWithValue(fields[i], keys[i]); + terms.Add("`" + fields[i] + "` = ?" + fields[i]); + } - cmd.CommandText = String.Format("delete from {0} where `{1}` = ?{1}", m_Realm, field); - cmd.Parameters.AddWithValue(field, val); + string where = String.Join(" and ", terms.ToArray()); - if (ExecuteNonQuery(cmd) > 0) - return true; + string query = String.Format("delete from {0} where {1}", m_Realm, where); - return false; + cmd.CommandText = query; + + return ExecuteNonQuery(cmd) > 0; } } } diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs index 481da493a3..caf18a4780 100644 --- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs @@ -85,11 +85,21 @@ namespace OpenSim.Data.MySQL return m_Folders.Delete(field, val); } + public bool DeleteFolders(string[] fields, string[] vals) + { + return m_Folders.Delete(fields, vals); + } + public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } + public bool DeleteItems(string[] fields, string[] vals) + { + return m_Items.Delete(fields, vals); + } + public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); diff --git a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs index 0d7b001e3f..3fb2d3facb 100644 --- a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs +++ b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs @@ -258,17 +258,33 @@ namespace OpenSim.Data.SQLite return false; } - public bool Delete(string field, string val) + public virtual bool Delete(string field, string key) { + return Delete(new string[] { field }, new string[] { key }); + } + + public bool Delete(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return false; + + List terms = new List(); + SqliteCommand cmd = new SqliteCommand(); - cmd.CommandText = String.Format("delete from {0} where `{1}` = :{1}", m_Realm, field); - cmd.Parameters.Add(new SqliteParameter(field, val)); + for (int i = 0 ; i < fields.Length ; i++) + { + cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i])); + terms.Add("`" + fields[i] + "` = :" + fields[i]); + } - if (ExecuteNonQuery(cmd, m_Connection) > 0) - return true; + string where = String.Join(" and ", terms.ToArray()); - return false; + string query = String.Format("delete * from {0} where {1}", m_Realm, where); + + cmd.CommandText = query; + + return ExecuteNonQuery(cmd, m_Connection) > 0; } } } diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs index ccbd86e119..02edc30707 100644 --- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs +++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs @@ -91,11 +91,21 @@ namespace OpenSim.Data.SQLite return m_Folders.Delete(field, val); } + public bool DeleteFolders(string[] fields, string[] vals) + { + return m_Folders.Delete(fields, vals); + } + public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } + public bool DeleteItems(string[] fields, string[] vals) + { + return m_Items.Delete(fields, vals); + } + public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 0af35c84ac..a094a02a43 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -411,12 +411,30 @@ namespace OpenSim.Services.InventoryService public virtual bool DeleteItems(UUID principalID, List itemIDs) { if (!m_AllowDelete) - return false; - - // Just use the ID... *facepalms* - // - foreach (UUID id in itemIDs) - m_Database.DeleteItems("inventoryID", id.ToString()); + { + // We must still allow links and links to folders to be deleted, otherwise they will build up + // in the player's inventory until they can no longer log in. Deletions of links due to code bugs or + // similar is inconvenient but on a par with accidental movement of items. The original item is never + // touched. + foreach (UUID id in itemIDs) + { + if (!m_Database.DeleteItems( + new string[] { "inventoryID", "assetType" }, + new string[] { id.ToString(), ((sbyte)AssetType.Link).ToString() })); + { + m_Database.DeleteItems( + new string[] { "inventoryID", "assetType" }, + new string[] { id.ToString(), ((sbyte)AssetType.LinkFolder).ToString() }); + } + } + } + else + { + // Just use the ID... *facepalms* + // + foreach (UUID id in itemIDs) + m_Database.DeleteItems("inventoryID", id.ToString()); + } return true; } From c562b9ef19d230fa7a0ee31f40224c9967751661 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 18 May 2011 00:22:09 +0100 Subject: [PATCH 017/186] correct small mistake in "delete object name " usage summary --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 76ab299742..9df73408bb 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -597,7 +597,7 @@ namespace OpenSim.Region.Framework.Scenes "delete object uuid ", "Delete object by uuid", HandleDeleteObject); MainConsole.Instance.Commands.AddCommand("region", false, "delete object name", - "delete object name ", + "delete object name ", "Delete object by name", HandleDeleteObject); //Bind Storage Manager functions to some land manager functions for this scene From 6dcc87b1adeb71a9c83cafa95a95a80c50b62092 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 18 May 2011 00:23:35 +0100 Subject: [PATCH 018/186] Accidentally committed too early Revert "Allow item links to be deleted even when other deletes and purges are disabled." This reverts commit 491279f99afc65860d44765ee7829c7dd5e4e38e. --- OpenSim/Data/IXInventoryData.cs | 29 --------------- .../Data/MSSQL/MSSQLGenericTableHandler.cs | 35 +++++++------------ OpenSim/Data/MSSQL/MSSQLXInventoryData.cs | 10 ------ .../Data/MySQL/MySQLGenericTableHandler.cs | 27 ++++---------- OpenSim/Data/MySQL/MySQLXInventoryData.cs | 10 ------ .../Data/SQLite/SQLiteGenericTableHandler.cs | 28 ++++----------- OpenSim/Data/SQLite/SQLiteXInventoryData.cs | 10 ------ .../InventoryService/XInventoryService.cs | 30 ++++------------ 8 files changed, 30 insertions(+), 149 deletions(-) diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs index 85a5c08d37..d85a7efb8f 100644 --- a/OpenSim/Data/IXInventoryData.cs +++ b/OpenSim/Data/IXInventoryData.cs @@ -74,38 +74,9 @@ namespace OpenSim.Data bool StoreFolder(XInventoryFolder folder); bool StoreItem(XInventoryItem item); - /// - /// Delete folders where field == val - /// - /// - /// - /// true if the delete was successful, false if it was not bool DeleteFolders(string field, string val); - - /// - /// Delete folders where field1 == val1, field2 == val2... - /// - /// - /// - /// true if the delete was successful, false if it was not - bool DeleteFolders(string[] fields, string[] vals); - - /// - /// Delete items where field == val - /// - /// - /// - /// true if the delete was successful, false if it was not bool DeleteItems(string field, string val); - /// - /// Delete items where field1 == val1, field2 == val2... - /// - /// - /// - /// true if the delete was successful, false if it was not - bool DeleteItems(string[] fields, string[] vals); - bool MoveItem(string id, string newParent); XInventoryItem[] GetActiveGestures(UUID principalID); int GetAssetPermissions(UUID principalID, UUID assetID); diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs index 317afac493..f5492b3050 100644 --- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs +++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs @@ -335,35 +335,24 @@ namespace OpenSim.Data.MSSQL } } - public virtual bool Delete(string field, string key) + public virtual bool Delete(string field, string val) { - return Delete(new string[] { field }, new string[] { key }); - } - - public virtual bool Delete(string[] fields, string[] keys) - { - if (fields.Length != keys.Length) - return false; - - List terms = new List(); - using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) { - for (int i = 0; i < fields.Length; i++) - { - cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i])); - terms.Add("[" + fields[i] + "] = @" + fields[i]); - } - - string where = String.Join(" AND ", terms.ToArray()); - - string query = String.Format("DELETE * FROM {0} WHERE {1}", m_Realm, where); - + string deleteCommand = String.Format("DELETE FROM {0} WHERE [{1}] = @{1}", m_Realm, field); + cmd.CommandText = deleteCommand; + + cmd.Parameters.Add(m_database.CreateParameter(field, val)); cmd.Connection = conn; - cmd.CommandText = query; conn.Open(); - return cmd.ExecuteNonQuery() > 0; + + if (cmd.ExecuteNonQuery() > 0) + { + //m_log.Warn("[MSSQLGenericTable]: " + deleteCommand); + return true; + } + return false; } } } diff --git a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs index 01689a43e6..5bc4fe41e5 100644 --- a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs +++ b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs @@ -79,21 +79,11 @@ namespace OpenSim.Data.MSSQL return m_Folders.Delete(field, val); } - public bool DeleteFolders(string[] fields, string[] vals) - { - return m_Folders.Delete(fields, vals); - } - public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } - public bool DeleteItems(string[] fields, string[] vals) - { - return m_Items.Delete(fields, vals); - } - public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index 754cf725f0..cfffbd8739 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -264,33 +264,18 @@ namespace OpenSim.Data.MySQL } } - public virtual bool Delete(string field, string key) + public virtual bool Delete(string field, string val) { - return Delete(new string[] { field }, new string[] { key }); - } - - public virtual bool Delete(string[] fields, string[] keys) - { - if (fields.Length != keys.Length) - return false; - - List terms = new List(); - using (MySqlCommand cmd = new MySqlCommand()) { - for (int i = 0 ; i < fields.Length ; i++) - { - cmd.Parameters.AddWithValue(fields[i], keys[i]); - terms.Add("`" + fields[i] + "` = ?" + fields[i]); - } - string where = String.Join(" and ", terms.ToArray()); + cmd.CommandText = String.Format("delete from {0} where `{1}` = ?{1}", m_Realm, field); + cmd.Parameters.AddWithValue(field, val); - string query = String.Format("delete from {0} where {1}", m_Realm, where); + if (ExecuteNonQuery(cmd) > 0) + return true; - cmd.CommandText = query; - - return ExecuteNonQuery(cmd) > 0; + return false; } } } diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs index caf18a4780..481da493a3 100644 --- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs @@ -85,21 +85,11 @@ namespace OpenSim.Data.MySQL return m_Folders.Delete(field, val); } - public bool DeleteFolders(string[] fields, string[] vals) - { - return m_Folders.Delete(fields, vals); - } - public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } - public bool DeleteItems(string[] fields, string[] vals) - { - return m_Items.Delete(fields, vals); - } - public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); diff --git a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs index 3fb2d3facb..0d7b001e3f 100644 --- a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs +++ b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs @@ -258,33 +258,17 @@ namespace OpenSim.Data.SQLite return false; } - public virtual bool Delete(string field, string key) + public bool Delete(string field, string val) { - return Delete(new string[] { field }, new string[] { key }); - } - - public bool Delete(string[] fields, string[] keys) - { - if (fields.Length != keys.Length) - return false; - - List terms = new List(); - SqliteCommand cmd = new SqliteCommand(); - for (int i = 0 ; i < fields.Length ; i++) - { - cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i])); - terms.Add("`" + fields[i] + "` = :" + fields[i]); - } + cmd.CommandText = String.Format("delete from {0} where `{1}` = :{1}", m_Realm, field); + cmd.Parameters.Add(new SqliteParameter(field, val)); - string where = String.Join(" and ", terms.ToArray()); + if (ExecuteNonQuery(cmd, m_Connection) > 0) + return true; - string query = String.Format("delete * from {0} where {1}", m_Realm, where); - - cmd.CommandText = query; - - return ExecuteNonQuery(cmd, m_Connection) > 0; + return false; } } } diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs index 02edc30707..ccbd86e119 100644 --- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs +++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs @@ -91,21 +91,11 @@ namespace OpenSim.Data.SQLite return m_Folders.Delete(field, val); } - public bool DeleteFolders(string[] fields, string[] vals) - { - return m_Folders.Delete(fields, vals); - } - public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } - public bool DeleteItems(string[] fields, string[] vals) - { - return m_Items.Delete(fields, vals); - } - public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index a094a02a43..0af35c84ac 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -411,30 +411,12 @@ namespace OpenSim.Services.InventoryService public virtual bool DeleteItems(UUID principalID, List itemIDs) { if (!m_AllowDelete) - { - // We must still allow links and links to folders to be deleted, otherwise they will build up - // in the player's inventory until they can no longer log in. Deletions of links due to code bugs or - // similar is inconvenient but on a par with accidental movement of items. The original item is never - // touched. - foreach (UUID id in itemIDs) - { - if (!m_Database.DeleteItems( - new string[] { "inventoryID", "assetType" }, - new string[] { id.ToString(), ((sbyte)AssetType.Link).ToString() })); - { - m_Database.DeleteItems( - new string[] { "inventoryID", "assetType" }, - new string[] { id.ToString(), ((sbyte)AssetType.LinkFolder).ToString() }); - } - } - } - else - { - // Just use the ID... *facepalms* - // - foreach (UUID id in itemIDs) - m_Database.DeleteItems("inventoryID", id.ToString()); - } + return false; + + // Just use the ID... *facepalms* + // + foreach (UUID id in itemIDs) + m_Database.DeleteItems("inventoryID", id.ToString()); return true; } From bdd7849094996392417ea3e5080578a04b69afac Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 19 May 2011 00:51:14 +0100 Subject: [PATCH 019/186] Allow item links to be deleted even when other deletes and purges are disabled. If these links are not deleted, then they will build up in the player's inventory until they can no longer log in. Accidental deletion of links due to bugs or other causes is potentially inconvenient but on a par with items being accidentally moved. When a link is deleted, the target of the link is never touched. This is a general solution that accounts for the use of links anywhere in the user's inventory. --- OpenSim/Data/IXInventoryData.cs | 29 +++++++++++++++ .../Data/MSSQL/MSSQLGenericTableHandler.cs | 35 ++++++++++++------- OpenSim/Data/MSSQL/MSSQLXInventoryData.cs | 10 ++++++ .../Data/MySQL/MySQLGenericTableHandler.cs | 27 ++++++++++---- OpenSim/Data/MySQL/MySQLXInventoryData.cs | 10 ++++++ .../Data/SQLite/SQLiteGenericTableHandler.cs | 28 +++++++++++---- OpenSim/Data/SQLite/SQLiteXInventoryData.cs | 10 ++++++ .../InventoryService/XInventoryService.cs | 34 ++++++++++++++---- 8 files changed, 153 insertions(+), 30 deletions(-) diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs index d85a7efb8f..85a5c08d37 100644 --- a/OpenSim/Data/IXInventoryData.cs +++ b/OpenSim/Data/IXInventoryData.cs @@ -74,9 +74,38 @@ namespace OpenSim.Data bool StoreFolder(XInventoryFolder folder); bool StoreItem(XInventoryItem item); + /// + /// Delete folders where field == val + /// + /// + /// + /// true if the delete was successful, false if it was not bool DeleteFolders(string field, string val); + + /// + /// Delete folders where field1 == val1, field2 == val2... + /// + /// + /// + /// true if the delete was successful, false if it was not + bool DeleteFolders(string[] fields, string[] vals); + + /// + /// Delete items where field == val + /// + /// + /// + /// true if the delete was successful, false if it was not bool DeleteItems(string field, string val); + /// + /// Delete items where field1 == val1, field2 == val2... + /// + /// + /// + /// true if the delete was successful, false if it was not + bool DeleteItems(string[] fields, string[] vals); + bool MoveItem(string id, string newParent); XInventoryItem[] GetActiveGestures(UUID principalID); int GetAssetPermissions(UUID principalID, UUID assetID); diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs index f5492b3050..317afac493 100644 --- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs +++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs @@ -335,24 +335,35 @@ namespace OpenSim.Data.MSSQL } } - public virtual bool Delete(string field, string val) + public virtual bool Delete(string field, string key) { + return Delete(new string[] { field }, new string[] { key }); + } + + public virtual bool Delete(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return false; + + List terms = new List(); + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) { - string deleteCommand = String.Format("DELETE FROM {0} WHERE [{1}] = @{1}", m_Realm, field); - cmd.CommandText = deleteCommand; - - cmd.Parameters.Add(m_database.CreateParameter(field, val)); - cmd.Connection = conn; - conn.Open(); - - if (cmd.ExecuteNonQuery() > 0) + for (int i = 0; i < fields.Length; i++) { - //m_log.Warn("[MSSQLGenericTable]: " + deleteCommand); - return true; + cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i])); + terms.Add("[" + fields[i] + "] = @" + fields[i]); } - return false; + + string where = String.Join(" AND ", terms.ToArray()); + + string query = String.Format("DELETE * FROM {0} WHERE {1}", m_Realm, where); + + cmd.Connection = conn; + cmd.CommandText = query; + conn.Open(); + return cmd.ExecuteNonQuery() > 0; } } } diff --git a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs index 5bc4fe41e5..01689a43e6 100644 --- a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs +++ b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs @@ -79,11 +79,21 @@ namespace OpenSim.Data.MSSQL return m_Folders.Delete(field, val); } + public bool DeleteFolders(string[] fields, string[] vals) + { + return m_Folders.Delete(fields, vals); + } + public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } + public bool DeleteItems(string[] fields, string[] vals) + { + return m_Items.Delete(fields, vals); + } + public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index cfffbd8739..754cf725f0 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -264,18 +264,33 @@ namespace OpenSim.Data.MySQL } } - public virtual bool Delete(string field, string val) + public virtual bool Delete(string field, string key) { + return Delete(new string[] { field }, new string[] { key }); + } + + public virtual bool Delete(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return false; + + List terms = new List(); + using (MySqlCommand cmd = new MySqlCommand()) { + for (int i = 0 ; i < fields.Length ; i++) + { + cmd.Parameters.AddWithValue(fields[i], keys[i]); + terms.Add("`" + fields[i] + "` = ?" + fields[i]); + } - cmd.CommandText = String.Format("delete from {0} where `{1}` = ?{1}", m_Realm, field); - cmd.Parameters.AddWithValue(field, val); + string where = String.Join(" and ", terms.ToArray()); - if (ExecuteNonQuery(cmd) > 0) - return true; + string query = String.Format("delete from {0} where {1}", m_Realm, where); - return false; + cmd.CommandText = query; + + return ExecuteNonQuery(cmd) > 0; } } } diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs index 481da493a3..caf18a4780 100644 --- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs @@ -85,11 +85,21 @@ namespace OpenSim.Data.MySQL return m_Folders.Delete(field, val); } + public bool DeleteFolders(string[] fields, string[] vals) + { + return m_Folders.Delete(fields, vals); + } + public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } + public bool DeleteItems(string[] fields, string[] vals) + { + return m_Items.Delete(fields, vals); + } + public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); diff --git a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs index 0d7b001e3f..3fb2d3facb 100644 --- a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs +++ b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs @@ -258,17 +258,33 @@ namespace OpenSim.Data.SQLite return false; } - public bool Delete(string field, string val) + public virtual bool Delete(string field, string key) { + return Delete(new string[] { field }, new string[] { key }); + } + + public bool Delete(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return false; + + List terms = new List(); + SqliteCommand cmd = new SqliteCommand(); - cmd.CommandText = String.Format("delete from {0} where `{1}` = :{1}", m_Realm, field); - cmd.Parameters.Add(new SqliteParameter(field, val)); + for (int i = 0 ; i < fields.Length ; i++) + { + cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i])); + terms.Add("`" + fields[i] + "` = :" + fields[i]); + } - if (ExecuteNonQuery(cmd, m_Connection) > 0) - return true; + string where = String.Join(" and ", terms.ToArray()); - return false; + string query = String.Format("delete * from {0} where {1}", m_Realm, where); + + cmd.CommandText = query; + + return ExecuteNonQuery(cmd, m_Connection) > 0; } } } diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs index ccbd86e119..02edc30707 100644 --- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs +++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs @@ -91,11 +91,21 @@ namespace OpenSim.Data.SQLite return m_Folders.Delete(field, val); } + public bool DeleteFolders(string[] fields, string[] vals) + { + return m_Folders.Delete(fields, vals); + } + public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } + public bool DeleteItems(string[] fields, string[] vals) + { + return m_Items.Delete(fields, vals); + } + public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 0af35c84ac..2282ee85bc 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -393,6 +393,10 @@ namespace OpenSim.Services.InventoryService public virtual bool UpdateItem(InventoryItemBase item) { + if (!m_AllowDelete) + if (item.AssetType == (sbyte)AssetType.Link || item.AssetType == (sbyte)AssetType.LinkFolder) + return false; + return m_Database.StoreItem(ConvertFromOpenSim(item)); } @@ -411,12 +415,30 @@ namespace OpenSim.Services.InventoryService public virtual bool DeleteItems(UUID principalID, List itemIDs) { if (!m_AllowDelete) - return false; - - // Just use the ID... *facepalms* - // - foreach (UUID id in itemIDs) - m_Database.DeleteItems("inventoryID", id.ToString()); + { + // We must still allow links and links to folders to be deleted, otherwise they will build up + // in the player's inventory until they can no longer log in. Deletions of links due to code bugs or + // similar is inconvenient but on a par with accidental movement of items. The original item is never + // touched. + foreach (UUID id in itemIDs) + { + if (!m_Database.DeleteItems( + new string[] { "inventoryID", "assetType" }, + new string[] { id.ToString(), ((sbyte)AssetType.Link).ToString() })); + { + m_Database.DeleteItems( + new string[] { "inventoryID", "assetType" }, + new string[] { id.ToString(), ((sbyte)AssetType.LinkFolder).ToString() }); + } + } + } + else + { + // Just use the ID... *facepalms* + // + foreach (UUID id in itemIDs) + m_Database.DeleteItems("inventoryID", id.ToString()); + } return true; } From 926a100652dcd06e012e66e873bf3f8dd63f6369 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Thu, 19 May 2011 01:34:11 -0400 Subject: [PATCH 020/186] Add stub for llGetLinkNumberOfSides(integer link) --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 02402271c1..cb3bddc780 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4458,6 +4458,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return result; } + public void llGetLinkNumberOfSides(int link) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetLinkNumberOfSides"); + } + public LSL_Integer llGetNumberOfSides() { m_host.AddScriptLPS(1); From d21e9c755f004d8fe03b11bc57b810dbd401435a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 19 May 2011 16:54:46 -0700 Subject: [PATCH 021/186] HG Friends working to some extent: friendships offered and accepted correctly handled. Friends list showing correct foreign names. TODO: GrantRights. --- OpenSim/Data/IFriendsData.cs | 2 +- .../MySQL/Resources/FriendsStore.migrations | 6 + OpenSim/Data/Null/NullFriendsData.cs | 4 +- OpenSim/Framework/AgentCircuitData.cs | 1 + OpenSim/Framework/AssetBase.cs | 6 + OpenSim/Framework/Util.cs | 61 +++ .../Avatar/Friends/FriendsModule.cs | 153 ++++-- .../Avatar/Friends/HGFriendsModule.cs | 438 ++++++++++++++++++ .../UserManagement/UserManagementModule.cs | 2 + .../HypergridServiceInConnectorModule.cs | 1 + .../Handlers/Friends/FriendServerConnector.cs | 6 +- .../Friends/FriendsServerPostHandler.cs | 2 +- .../Hypergrid/HGFriendServerConnector.cs | 71 +++ .../Hypergrid/HGFriendsServerPostHandler.cs | 242 ++++++++++ .../Friends/FriendsServiceConnector.cs | 13 +- .../Hypergrid/HGFriendsServiceConnector.cs | 175 +++++++ .../SimianFriendsServiceConnector.cs | 2 +- OpenSim/Services/Friends/FriendsService.cs | 9 +- .../HypergridService/HGFriendsService.cs | 95 ++++ .../Services/Interfaces/IFriendsService.cs | 2 +- .../LLLoginService/LLLoginResponse.cs | 14 +- bin/config-include/StandaloneHypergrid.ini | 5 + prebuild.xml | 1 + 23 files changed, 1253 insertions(+), 58 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs create mode 100644 OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs create mode 100644 OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs create mode 100644 OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs create mode 100644 OpenSim/Services/HypergridService/HGFriendsService.cs diff --git a/OpenSim/Data/IFriendsData.cs b/OpenSim/Data/IFriendsData.cs index 1f1a0316f6..4da567e56b 100644 --- a/OpenSim/Data/IFriendsData.cs +++ b/OpenSim/Data/IFriendsData.cs @@ -34,7 +34,7 @@ namespace OpenSim.Data { public class FriendsData { - public UUID PrincipalID; + public string PrincipalID; public string Friend; public Dictionary Data; } diff --git a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations index ce713bdb89..35e5e93cde 100644 --- a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations +++ b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations @@ -21,5 +21,11 @@ INSERT INTO `Friends` SELECT `ownerID`, `friendID`, `friendPerms`, 0 FROM `userf COMMIT; +:VERSION 3 # ------------------------- +BEGIN; + +ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; + +COMMIT; diff --git a/OpenSim/Data/Null/NullFriendsData.cs b/OpenSim/Data/Null/NullFriendsData.cs index e7f7fd3738..0c69bb1700 100644 --- a/OpenSim/Data/Null/NullFriendsData.cs +++ b/OpenSim/Data/Null/NullFriendsData.cs @@ -53,7 +53,7 @@ namespace OpenSim.Data.Null { List lst = m_Data.FindAll(delegate (FriendsData fdata) { - return fdata.PrincipalID == userID; + return fdata.PrincipalID == userID.ToString(); }); if (lst != null) @@ -74,7 +74,7 @@ namespace OpenSim.Data.Null public bool Delete(UUID userID, string friendID) { - List lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID; }); + List lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID.ToString(); }); if (lst != null) { FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; }); diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs index dbd47d392a..125910e5bc 100644 --- a/OpenSim/Framework/AgentCircuitData.cs +++ b/OpenSim/Framework/AgentCircuitData.cs @@ -345,6 +345,7 @@ namespace OpenSim.Framework } } } + } diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs index 53d28be088..5f68cdaabf 100644 --- a/OpenSim/Framework/AssetBase.cs +++ b/OpenSim/Framework/AssetBase.cs @@ -215,6 +215,12 @@ namespace OpenSim.Framework set { m_metadata.Temporary = value; } } + public string CreatorID + { + get { return m_metadata.CreatorID; } + set { m_metadata.CreatorID = value; } + } + public AssetFlags Flags { get { return m_metadata.Flags; } diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index aaa2724532..af21cb55cc 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1694,5 +1694,66 @@ namespace OpenSim.Framework return (T)Enum.Parse(typeof(T), value); ; } #endregion + + #region Universal User Identifiers + /// + /// + /// uuid[;endpoint[;name]] + /// + /// + /// + /// + public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname) + { + uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; + + string[] parts = value.Split(';'); + if (parts.Length >= 1) + if (!UUID.TryParse(parts[0], out uuid)) + return false; + + if (parts.Length >= 2) + url = parts[1]; + + if (parts.Length >= 3) + { + string[] name = parts[2].Split(); + if (name.Length == 2) + { + firstname = name[0]; + lastname = name[1]; + } + } + + return true; + } + + /// + /// + /// + /// + /// uuid[;endpoint[;name]] + public static string ProduceUserUniversalIdentifier(AgentCircuitData acircuit) + { + if (acircuit.ServiceURLs.ContainsKey("HomeURI")) + { + string agentsURI = acircuit.ServiceURLs["HomeURI"].ToString(); + if (!agentsURI.EndsWith("/")) + agentsURI += "/"; + + // This is ugly, but there's no other way, given that the name is changed + // in the agent circuit data for foreigners + if (acircuit.lastname.Contains("@")) + { + string[] parts = acircuit.firstname.Split(new char[] { '.' }); + if (parts.Length == 2) + return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1]; + } + return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + acircuit.firstname + " " + acircuit.lastname; + } + else + return acircuit.AgentID.ToString(); + } + #endregion } } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 5baf0785f4..21cd924583 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -49,6 +49,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { public class FriendsModule : ISharedRegionModule, IFriendsModule { + protected bool m_Enabled = false; + protected class UserFriendData { public UUID PrincipalID; @@ -130,7 +132,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } + #region ISharedRegionModule public void Initialise(IConfigSource config) + { + IConfig moduleConfig = config.Configs["Modules"]; + if (moduleConfig != null) + { + string name = moduleConfig.GetString("FriendsModule", "FriendsModule"); + m_log.DebugFormat("[XXX] {0} compared to {1}", name, Name); + if (name == Name) + { + InitModule(config); + + m_Enabled = true; + m_log.InfoFormat("[FRIENDS MODULE]: {0} enabled.", Name); + } + } + } + + protected void InitModule(IConfigSource config) { IConfig friendsConfig = config.Configs["Friends"]; if (friendsConfig != null) @@ -153,7 +173,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_log.Error("[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue"); throw new Exception("Connector load error"); } - } public void PostInitialise() @@ -166,6 +185,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends public void AddRegion(Scene scene) { + if (!m_Enabled) + return; + m_Scenes.Add(scene); scene.RegisterModuleInterface(this); @@ -181,10 +203,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends public void RemoveRegion(Scene scene) { + if (!m_Enabled) + return; + m_Scenes.Remove(scene); } - public string Name + public virtual string Name { get { return "FriendsModule"; } } @@ -194,6 +219,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends get { return null; } } + #endregion + public uint GetFriendPerms(UUID principalID, UUID friendID) { FriendInfo[] friends = GetFriends(principalID); @@ -214,30 +241,33 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.OnTerminateFriendship += OnTerminateFriendship; client.OnGrantUserRights += OnGrantUserRights; - // Asynchronously fetch the friends list or increment the refcount for the existing - // friends list - Util.FireAndForget( - delegate(object o) - { - lock (m_Friends) - { - UserFriendData friendsData; - if (m_Friends.TryGetValue(client.AgentId, out friendsData)) - { - friendsData.Refcount++; - } - else - { - friendsData = new UserFriendData(); - friendsData.PrincipalID = client.AgentId; - friendsData.Friends = FriendsService.GetFriends(client.AgentId); - friendsData.Refcount = 1; + Util.FireAndForget(delegate { FetchFriendslist(client.AgentId); }); + } - m_Friends[client.AgentId] = friendsData; - } - } + /// Fetch the friends list or increment the refcount for the existing + /// friends list + /// Returns true if the list was fetched, false if it wasn't + protected virtual bool FetchFriendslist(UUID agentID) + { + lock (m_Friends) + { + UserFriendData friendsData; + if (m_Friends.TryGetValue(agentID, out friendsData)) + { + friendsData.Refcount++; + return false; } - ); + else + { + friendsData = new UserFriendData(); + friendsData.PrincipalID = agentID; + friendsData.Friends = FriendsService.GetFriends(agentID); + friendsData.Refcount = 1; + + m_Friends[agentID] = friendsData; + return true; + } + } } private void OnClientClosed(UUID agentID, Scene scene) @@ -313,10 +343,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends foreach (string fid in outstanding) { UUID fromAgentID; - if (!UUID.TryParse(fid, out fromAgentID)) + string firstname = "Unknown", lastname = "User"; + if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname)) + { + m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid); continue; - - UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID); + } PresenceInfo presence = null; PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); @@ -326,15 +358,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends im.offline = 0; im.fromAgentID = fromAgentID.Guid; - im.fromAgentName = account.FirstName + " " + account.LastName; + im.fromAgentName = firstname + " " + lastname; im.offline = (byte)((presence == null) ? 1 : 0); im.imSessionID = im.fromAgentID; + im.message = FriendshipMessage(fid); // Finally LocalFriendshipOffered(agentID, im); } } + protected virtual string FriendshipMessage(string friendID) + { + return "Will you be my friend?"; + } + + protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) + { + first = "Unknown"; last = "User"; + if (!UUID.TryParse(fid, out agentID)) + return false; + + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(scopeID, agentID); + if (account != null) + { + first = account.FirstName; + last = account.LastName; + } + + return true; + } + List GetOnlineFriends(UUID userID) { List friendList = new List(); @@ -475,23 +529,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // This user wants to be friends with the other user. // Let's add the relation backwards, in case the other is not online - FriendsService.StoreFriend(friendID, principalID.ToString(), 0); + StoreBackwards(friendID, principalID); // Now let's ask the other user to be friends with this user ForwardFriendshipOffer(principalID, friendID, im); } } + protected virtual void StoreBackwards(UUID friendID, UUID agentID) + { + FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0); + } + private void ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im) { // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID) // We stick this agent's ID as imSession, so that it's directly available on the receiving end im.imSessionID = im.fromAgentID; + im.fromAgentName = GetFriendshipRequesterName(agentID); - // Try the local sim - UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID); - im.fromAgentName = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; - + // Try the local sim if (LocalFriendshipOffered(friendID, im)) return; @@ -509,12 +566,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // If the prospective friend is not online, he'll get the message upon login. } + protected virtual string GetFriendshipRequesterName(UUID agentID) + { + UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID); + return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; + } + private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) { m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID); - - FriendsService.StoreFriend(agentID, friendID.ToString(), 1); - FriendsService.StoreFriend(friendID, agentID.ToString(), 1); + + StoreFriendships(agentID, friendID); // Update the local cache UpdateFriendsCache(agentID); @@ -544,6 +606,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } + protected virtual void StoreFriendships(UUID agentID, UUID friendID) + { + FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), 1); + FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 1); + } + private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) { m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID); @@ -576,8 +644,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) { - FriendsService.Delete(agentID, exfriendID.ToString()); - FriendsService.Delete(exfriendID, agentID.ToString()); + DeleteFriendship(agentID, exfriendID); // Update local cache UpdateFriendsCache(agentID); @@ -604,6 +671,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } + protected virtual void DeleteFriendship(UUID agentID, UUID exfriendID) + { + FriendsService.Delete(agentID, exfriendID.ToString()); + FriendsService.Delete(exfriendID, agentID.ToString()); + } + private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) { FriendInfo[] friends = GetFriends(remoteClient.AgentId); @@ -622,7 +695,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (friend != null) // Found it { // Store it on the DB - FriendsService.StoreFriend(requester, target.ToString(), rights); + FriendsService.StoreFriend(requester.ToString(), target.ToString(), rights); // Store it in the local cache int myFlags = friend.MyFlags; @@ -780,7 +853,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion - private FriendInfo[] GetFriends(UUID agentID) + protected FriendInfo[] GetFriends(UUID agentID) { UserFriendData friendsData; diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs new file mode 100644 index 0000000000..645ecdc011 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -0,0 +1,438 @@ +/* + * 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 Mono.Addins; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.Hypergrid; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; +using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.CoreModules.Avatar.Friends +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #region ISharedRegionModule + public override string Name + { + get { return "HGFriendsModule"; } + } + + #endregion + + //public void SendFriendsOnlineIfNeeded(IClientAPI client) + //{ + // UUID agentID = client.AgentId; + + // // Check if the online friends list is needed + // lock (m_NeedsListOfFriends) + // { + // if (!m_NeedsListOfFriends.Remove(agentID)) + // return; + // } + + // // Send the friends online + // List online = GetOnlineFriends(agentID); + // if (online.Count > 0) + // { + // m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count); + // client.SendAgentOnline(online.ToArray()); + // } + + // // Send outstanding friendship offers + // List outstanding = new List(); + // FriendInfo[] friends = GetFriends(agentID); + // foreach (FriendInfo fi in friends) + // { + // if (fi.TheirFlags == -1) + // outstanding.Add(fi.Friend); + // } + + // GridInstantMessage im = new GridInstantMessage(client.Scene, UUID.Zero, String.Empty, agentID, (byte)InstantMessageDialog.FriendshipOffered, + // "Will you be my friend?", true, Vector3.Zero); + + // foreach (string fid in outstanding) + // { + // UUID fromAgentID; + // if (!UUID.TryParse(fid, out fromAgentID)) + // continue; + + // UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID); + + // PresenceInfo presence = null; + // PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); + // if (presences != null && presences.Length > 0) + // presence = presences[0]; + // if (presence != null) + // im.offline = 0; + + // im.fromAgentID = fromAgentID.Guid; + // im.fromAgentName = account.FirstName + " " + account.LastName; + // im.offline = (byte)((presence == null) ? 1 : 0); + // im.imSessionID = im.fromAgentID; + + // // Finally + // LocalFriendshipOffered(agentID, im); + // } + //} + + //List GetOnlineFriends(UUID userID) + //{ + // List friendList = new List(); + // List online = new List(); + + // FriendInfo[] friends = GetFriends(userID); + // foreach (FriendInfo fi in friends) + // { + // if (((fi.TheirFlags & 1) != 0) && (fi.TheirFlags != -1)) + // friendList.Add(fi.Friend); + // } + + // if (friendList.Count > 0) + // { + // PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray()); + // foreach (PresenceInfo pi in presence) + // { + // UUID presenceID; + // if (UUID.TryParse(pi.UserID, out presenceID)) + // online.Add(presenceID); + // } + // } + + // return online; + //} + + //private void StatusNotify(FriendInfo friend, UUID userID, bool online) + //{ + // UUID friendID; + // if (UUID.TryParse(friend.Friend, out friendID)) + // { + // // Try local + // if (LocalStatusNotification(userID, friendID, online)) + // return; + + // // The friend is not here [as root]. Let's forward. + // PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + // if (friendSessions != null && friendSessions.Length > 0) + // { + // PresenceInfo friendSession = null; + // foreach (PresenceInfo pinfo in friendSessions) + // if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad + // { + // friendSession = pinfo; + // break; + // } + + // if (friendSession != null) + // { + // GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + // //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); + // m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); + // } + // } + + // // Friend is not online. Ignore. + // } + // else + // { + // m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); + // } + //} + + protected override bool FetchFriendslist(UUID agentID) + { + if (base.FetchFriendslist(agentID)) + { + // We need to preload the user management cache with the names + // of foreign friends, just like we do with SOPs' creators + foreach (FriendInfo finfo in m_Friends[agentID].Friends) + { + if (finfo.TheirFlags != -1) + { + UUID id; + if (!UUID.TryParse(finfo.Friend, out id)) + { + string url = string.Empty, first = string.Empty, last = string.Empty; + if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last)) + { + IUserManagement uMan = m_Scenes[0].RequestModuleInterface(); + uMan.AddUser(id, url + ";" + first + " " + last); + } + } + } + } + return true; + } + return false; + } + + protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) + { + first = "Unknown"; last = "User"; + if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last)) + return true; + + // fid is not a UUID... + string url = string.Empty; + if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last)) + { + IUserManagement userMan = m_Scenes[0].RequestModuleInterface(); + userMan.AddUser(agentID, url + ";" + first + " " + last); + + try // our best + { + string[] parts = userMan.GetUserName(agentID).Split(); + first = parts[0]; + last = parts[1]; + } + catch { } + return true; + } + return false; + } + + protected override string GetFriendshipRequesterName(UUID agentID) + { + // For the time being we assume that HG friendship requests can only happen + // when avies are on the same region. + IClientAPI client = LocateClientObject(agentID); + if (client != null) + return client.FirstName + " " + client.LastName; + else + return base.GetFriendshipRequesterName(agentID); + } + + protected override string FriendshipMessage(string friendID) + { + UUID id; + if (UUID.TryParse(friendID, out id)) + return base.FriendshipMessage(friendID); + + return "Please confirm this friendship you made while you were away."; + } + + protected override void StoreBackwards(UUID friendID, UUID agentID) + { + UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID); + // Are they both local users? + if (account1 != null && account2 != null) + { + // local grid users + m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local"); + base.StoreBackwards(friendID, agentID); + return; + } + + // no provision for this temporary friendship state + //FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0); + } + + protected override void StoreFriendships(UUID agentID, UUID friendID) + { + UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID); + // Are they both local users? + if (agentAccount != null && friendAccount != null) + { + // local grid users + m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local"); + base.StoreFriendships(agentID, friendID); + return; + } + + + // ok, at least one of them is foreigner, let's get their data + IClientAPI agentClient = LocateClientObject(agentID); + IClientAPI friendClient = LocateClientObject(friendID); + AgentCircuitData agentClientCircuit = null; + AgentCircuitData friendClientCircuit = null; + string agentUUI = string.Empty; + string friendUUI = string.Empty; + string agentFriendService = string.Empty; + string friendFriendService = string.Empty; + + if (agentClient != null) + { + agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode); + agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); + agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); + } + if (friendClient != null) + { + friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode); + friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit); + friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); + } + + m_log.DebugFormat("[XXX] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}", + agentUUI, friendUUI, agentFriendService, friendFriendService); + + if (agentAccount != null) // agent is local, 'friend' is foreigner + { + // This may happen when the agent returned home, in which case the friend is not there + // We need to llok for its information in the friends list itself + if (friendUUI == string.Empty) + { + FriendInfo[] finfos = GetFriends(agentID); + foreach (FriendInfo finfo in finfos) + { + if (finfo.TheirFlags == -1) + { + if (finfo.Friend.StartsWith(friendID.ToString())) + friendUUI = finfo.Friend; + } + } + } + + // store in the local friends service a reference to the foreign friend + FriendsService.StoreFriend(agentID.ToString(), friendUUI, 1); + // and also the converse + FriendsService.StoreFriend(friendUUI, agentID.ToString(), 1); + + if (friendClientCircuit != null) + { + // store in the foreign friends service a reference to the local agent + HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(friendID, agentUUI); + } + } + else if (friendAccount != null) // 'friend' is local, agent is foreigner + { + // store in the local friends service a reference to the foreign agent + FriendsService.StoreFriend(friendID.ToString(), agentUUI, 1); + // and also the converse + FriendsService.StoreFriend(agentUUI, friendID.ToString(), 1); + + if (agentClientCircuit != null) + { + // store in the foreign friends service a reference to the local agent + HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(agentID, friendUUI); + } + } + else // They're both foreigners! + { + HGFriendsServicesConnector friendsConn; + if (agentClientCircuit != null) + { + friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(agentID, friendUUI); + } + if (friendClientCircuit != null) + { + friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(friendID, agentUUI); + } + } + // my brain hurts now + } + + protected override void DeleteFriendship(UUID agentID, UUID exfriendID) + { + base.DeleteFriendship(agentID, exfriendID); + // Maybe some of the base deletes will fail. + // Let's delete the local friendship with foreign friend + FriendInfo[] friends = GetFriends(agentID); + foreach (FriendInfo finfo in friends) + { + if (finfo.Friend != exfriendID.ToString() && finfo.Friend.EndsWith(exfriendID.ToString())) + { + FriendsService.Delete(agentID, exfriendID.ToString()); + // TODO: delete the friendship on the other side + // Should use the homeurl given in finfo.Friend + } + } + } + + //private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) + //{ + // FriendInfo[] friends = GetFriends(remoteClient.AgentId); + // if (friends.Length == 0) + // return; + + // m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); + // // Let's find the friend in this user's friend list + // FriendInfo friend = null; + // foreach (FriendInfo fi in friends) + // { + // if (fi.Friend == target.ToString()) + // friend = fi; + // } + + // if (friend != null) // Found it + // { + // // Store it on the DB + // FriendsService.StoreFriend(requester, target.ToString(), rights); + + // // Store it in the local cache + // int myFlags = friend.MyFlags; + // friend.MyFlags = rights; + + // // Always send this back to the original client + // remoteClient.SendChangeUserRights(requester, target, rights); + + // // + // // Notify the friend + // // + + // // Try local + // if (LocalGrantRights(requester, target, myFlags, rights)) + // return; + + // PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { target.ToString() }); + // if (friendSessions != null && friendSessions.Length > 0) + // { + // PresenceInfo friendSession = friendSessions[0]; + // if (friendSession != null) + // { + // GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + // // TODO: You might want to send the delta to save the lookup + // // on the other end!! + // m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights); + // } + // } + // } + //} + + + } +} diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 4cc6905a0f..795de098b2 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -141,6 +141,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) { + m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0}", uuid); if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) { remote_client.SendNameReply(uuid, "Mr", "OpenSim"); @@ -210,6 +211,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public string GetUserName(UUID uuid) { + m_log.DebugFormat("[XXX] GetUserName {0}", uuid); string[] names = GetUserNames(uuid); if (names.Length == 2) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs index d2343c994e..f5b6817638 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs @@ -115,6 +115,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid new UserAgentServerConnector(m_Config, MainServer.Instance); new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService"); + new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService"); } scene.RegisterModuleInterface(m_HypergridHandler.GateKeeper); } diff --git a/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs b/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs index 074f8690a5..5784bdf652 100644 --- a/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs +++ b/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs @@ -46,14 +46,14 @@ namespace OpenSim.Server.Handlers.Friends if (serverConfig == null) throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); - string gridService = serverConfig.GetString("LocalServiceModule", + string theService = serverConfig.GetString("LocalServiceModule", String.Empty); - if (gridService == String.Empty) + if (theService == String.Empty) throw new Exception("No LocalServiceModule in config file"); Object[] args = new Object[] { config }; - m_FriendsService = ServerUtils.LoadPlugin(gridService, args); + m_FriendsService = ServerUtils.LoadPlugin(theService, args); server.AddStreamHandler(new FriendsServerPostHandler(m_FriendsService)); } diff --git a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs index b168bb35c9..64002e1ada 100644 --- a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs @@ -138,7 +138,7 @@ namespace OpenSim.Server.Handlers.Friends { FriendInfo friend = new FriendInfo(request); - bool success = m_FriendsService.StoreFriend(friend.PrincipalID, friend.Friend, friend.MyFlags); + bool success = m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, friend.MyFlags); if (success) return SuccessResult(); diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs new file mode 100644 index 0000000000..82a72206d3 --- /dev/null +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs @@ -0,0 +1,71 @@ +/* + * 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; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.Hypergrid +{ + public class HGFriendsServerConnector : ServiceConnector + { + private IFriendsService m_FriendsService; + private IUserAgentService m_UserAgentService; + private string m_ConfigName = "HGFriendsService"; + + public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + if (configName != string.Empty) + m_ConfigName = configName; + + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); + + string theService = serverConfig.GetString("LocalServiceModule", + String.Empty); + + if (theService == String.Empty) + throw new Exception("No LocalServiceModule in config file"); + + Object[] args = new Object[] { config }; + m_FriendsService = ServerUtils.LoadPlugin(theService, args); + + theService = serverConfig.GetString("UserAgentService", string.Empty); + if (theService == String.Empty) + throw new Exception("No UserAgentService in " + m_ConfigName); + + m_UserAgentService = ServerUtils.LoadPlugin(theService, args); + + server.AddStreamHandler(new HGFriendsServerPostHandler(m_FriendsService, m_UserAgentService)); + } + } +} diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs new file mode 100644 index 0000000000..13d150265a --- /dev/null +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs @@ -0,0 +1,242 @@ +/* + * 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 Nini.Config; +using log4net; +using System; +using System.Reflection; +using System.IO; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; +using System.Xml.Serialization; +using System.Collections.Generic; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenMetaverse; + +namespace OpenSim.Server.Handlers.Hypergrid +{ + public class HGFriendsServerPostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IFriendsService m_FriendsService; + private IUserAgentService m_UserAgentService; + + public HGFriendsServerPostHandler(IFriendsService service, IUserAgentService uservice) : + base("POST", "/hgfriends") + { + m_FriendsService = service; + m_UserAgentService = uservice; + m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On"); + } + + public override byte[] Handle(string path, Stream requestData, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + //m_log.DebugFormat("[XXX]: query String: {0}", body); + + try + { + Dictionary request = + ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("METHOD")) + return FailureResult(); + + string method = request["METHOD"].ToString(); + + switch (method) + { + case "getfriends": + return GetFriends(request); + + case "newfriendship": + return NewFriendship(request); + + } + m_log.DebugFormat("[HGFRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method); + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS HANDLER]: Exception {0}", e); + } + + return FailureResult(); + + } + + #region Method-specific handlers + + byte[] GetFriends(Dictionary request) + { + UUID principalID = UUID.Zero; + if (request.ContainsKey("PRINCIPALID")) + UUID.TryParse(request["PRINCIPALID"].ToString(), out principalID); + else + m_log.WarnFormat("[HGFRIENDS HANDLER]: no principalID in request to get friends"); + + FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); + //m_log.DebugFormat("[FRIENDS HANDLER]: neighbours for region {0}: {1}", regionID, rinfos.Count); + + Dictionary result = new Dictionary(); + if ((finfos == null) || ((finfos != null) && (finfos.Length == 0))) + result["result"] = "null"; + else + { + int i = 0; + foreach (FriendInfo finfo in finfos) + { + Dictionary rinfoDict = finfo.ToKeyValuePairs(); + result["friend" + i] = rinfoDict; + i++; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + //m_log.DebugFormat("[FRIENDS HANDLER]: resp string: {0}", xmlString); + UTF8Encoding encoding = new UTF8Encoding(); + return encoding.GetBytes(xmlString); + + } + + byte[] NewFriendship(Dictionary request) + { + if (!request.ContainsKey("KEY") || !request.ContainsKey("SESSIONID")) + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: ignoring request without Key or SessionID"); + return FailureResult(); + } + + string serviceKey = request["KEY"].ToString(); + string sessionStr = request["SESSIONID"].ToString(); + UUID sessionID; + UUID.TryParse(sessionStr, out sessionID); + + if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey)) + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: Key {0} for session {1} did not match existing key. Ignoring request", serviceKey, sessionID); + return FailureResult(); + } + + m_log.DebugFormat("[XXX] Verification ok"); + // OK, can proceed + FriendInfo friend = new FriendInfo(request); + + // the user needs to confirm when he gets home + bool success = m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 0); + //if (success) + // m_FriendsService.StoreFriend(friend.Friend, friend.PrincipalID.ToString(), 1); + + if (success) + return SuccessResult(); + else + return FailureResult(); + } + + #endregion + + #region Misc + + private byte[] SuccessResult() + { + 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("Success")); + + rootElement.AppendChild(result); + + return DocToBytes(doc); + } + + private byte[] FailureResult() + { + return FailureResult(String.Empty); + } + + private byte[] FailureResult(string msg) + { + 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("Failure")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Message", ""); + message.AppendChild(doc.CreateTextNode(msg)); + + rootElement.AppendChild(message); + + 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(); + } + + #endregion + } +} diff --git a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs index 861c4759a3..52b80e1ffd 100644 --- a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs @@ -38,7 +38,7 @@ using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; using OpenSim.Server.Base; using OpenMetaverse; -namespace OpenSim.Services.Connectors +namespace OpenSim.Services.Connectors.Friends { public class FriendsServicesConnector : IFriendsService { @@ -144,10 +144,17 @@ namespace OpenSim.Services.Connectors } - public bool StoreFriend(UUID PrincipalID, string Friend, int flags) + public bool StoreFriend(string PrincipalID, string Friend, int flags) { FriendInfo finfo = new FriendInfo(); - finfo.PrincipalID = PrincipalID; + try + { + finfo.PrincipalID = new UUID(PrincipalID); + } + catch + { + return false; + } finfo.Friend = Friend; finfo.MyFlags = flags; diff --git a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs new file mode 100644 index 0000000000..76f5f190a9 --- /dev/null +++ b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs @@ -0,0 +1,175 @@ +/* + * 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.Services.Interfaces; +using OpenSim.Services.Connectors.Friends; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; +using OpenSim.Server.Base; +using OpenMetaverse; + +namespace OpenSim.Services.Connectors.Hypergrid +{ + public class HGFriendsServicesConnector + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI = String.Empty; + private string m_ServiceKey = String.Empty; + private UUID m_SessionID; + + public HGFriendsServicesConnector() + { + } + + public HGFriendsServicesConnector(string serverURI, UUID sessionID, string serviceKey) + { + m_ServerURI = serverURI.TrimEnd('/'); + m_ServiceKey = serviceKey; + m_SessionID = sessionID; + } + + #region IFriendsService + + public FriendInfo[] GetFriends(UUID PrincipalID) + { + Dictionary sendData = new Dictionary(); + + sendData["PRINCIPALID"] = PrincipalID.ToString(); + sendData["METHOD"] = "getfriends"; + sendData["KEY"] = m_ServiceKey; + sendData["SESSIONID"] = m_SessionID.ToString(); + + string reqString = ServerUtils.BuildQueryString(sendData); + + try + { + string reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/hgfriends", + reqString); + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData != null) + { + if (replyData.ContainsKey("result") && (replyData["result"].ToString().ToLower() == "null")) + { + return new FriendInfo[0]; + } + + List finfos = new List(); + Dictionary.ValueCollection finfosList = replyData.Values; + //m_log.DebugFormat("[FRIENDS CONNECTOR]: get neighbours returned {0} elements", rinfosList.Count); + foreach (object f in finfosList) + { + if (f is Dictionary) + { + FriendInfo finfo = new FriendInfo((Dictionary)f); + finfos.Add(finfo); + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriends {0} received invalid response type {1}", + PrincipalID, f.GetType()); + } + + // Success + return finfos.ToArray(); + } + + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriends {0} received null response", + PrincipalID); + + } + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message); + } + + return new FriendInfo[0]; + + } + + public bool NewFriendship(UUID PrincipalID, string Friend) + { + FriendInfo finfo = new FriendInfo(); + finfo.PrincipalID = PrincipalID; + finfo.Friend = Friend; + + Dictionary sendData = finfo.ToKeyValuePairs(); + + sendData["METHOD"] = "newfriendship"; + sendData["KEY"] = m_ServiceKey; + sendData["SESSIONID"] = m_SessionID.ToString(); + + string reply = string.Empty; + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/hgfriends", + ServerUtils.BuildQueryString(sendData)); + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message); + return false; + } + + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null)) + { + bool success = false; + Boolean.TryParse(replyData["Result"].ToString(), out success); + return success; + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend {0} {1} received null response", + PrincipalID, Friend); + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend received null reply"); + + return false; + + } + + #endregion + } +} \ No newline at end of file diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs index 6f2d73559b..f61ab2956d 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -127,7 +127,7 @@ namespace OpenSim.Services.Connectors.SimianGrid return array; } - public bool StoreFriend(UUID principalID, string friend, int flags) + public bool StoreFriend(string principalID, string friend, int flags) { if (String.IsNullOrEmpty(m_serverUrl)) return true; diff --git a/OpenSim/Services/Friends/FriendsService.cs b/OpenSim/Services/Friends/FriendsService.cs index 3c64eccdf6..039dc0bceb 100644 --- a/OpenSim/Services/Friends/FriendsService.cs +++ b/OpenSim/Services/Friends/FriendsService.cs @@ -43,17 +43,16 @@ namespace OpenSim.Services.Friends { } - public FriendInfo[] GetFriends(UUID PrincipalID) + public virtual FriendInfo[] GetFriends(UUID PrincipalID) { FriendsData[] data = m_Database.GetFriends(PrincipalID); - List info = new List(); foreach (FriendsData d in data) { FriendInfo i = new FriendInfo(); - i.PrincipalID = d.PrincipalID; + i.PrincipalID = new UUID(d.PrincipalID); i.Friend = d.Friend; i.MyFlags = Convert.ToInt32(d.Data["Flags"]); i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]); @@ -64,7 +63,7 @@ namespace OpenSim.Services.Friends return info.ToArray(); } - public bool StoreFriend(UUID PrincipalID, string Friend, int flags) + public virtual bool StoreFriend(string PrincipalID, string Friend, int flags) { FriendsData d = new FriendsData(); @@ -76,7 +75,7 @@ namespace OpenSim.Services.Friends return m_Database.Store(d); } - public bool Delete(UUID PrincipalID, string Friend) + public virtual bool Delete(UUID PrincipalID, string Friend) { return m_Database.Delete(PrincipalID, Friend); } diff --git a/OpenSim/Services/HypergridService/HGFriendsService.cs b/OpenSim/Services/HypergridService/HGFriendsService.cs new file mode 100644 index 0000000000..fa4ec5d7ec --- /dev/null +++ b/OpenSim/Services/HypergridService/HGFriendsService.cs @@ -0,0 +1,95 @@ +/* + * 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; +using OpenSim.Framework; +using System; +using System.Collections.Generic; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Friends; +using OpenSim.Data; +using Nini.Config; +using log4net; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; + +namespace OpenSim.Services.HypergridService +{ + public class HGFriendsService : FriendsService, IFriendsService + { + public HGFriendsService(IConfigSource config) : base(config) + { + } + + /// + /// Overrides base. + /// Storing new friendships from the outside is a tricky, sensitive operation, and it + /// needs to be done under certain restrictions. + /// First of all, if the friendship already exists, this is a no-op. In other words, + /// we cannot change just the flags, it needs to be a new friendship. + /// Second, we store it as flags=0 always, independent of what the caller sends. The + /// owner of the friendship needs to confirm when it gets back home. + /// + /// + /// + /// + /// + public override bool StoreFriend(string PrincipalID, string Friend, int flags) + { + UUID userID; + if (UUID.TryParse(PrincipalID, out userID)) + { + FriendsData[] friendsData = m_Database.GetFriends(userID); + List fList = new List(friendsData); + if (fList.Find(delegate(FriendsData fdata) + { + return fdata.Friend == Friend; + }) != null) + return false; + } + + FriendsData d = new FriendsData(); + d.PrincipalID = PrincipalID; + d.Friend = Friend; + d.Data = new Dictionary(); + d.Data["Flags"] = "0"; + + return m_Database.Store(d); + } + + /// + /// Overrides base. Cannot delete friendships while away from home. + /// + /// + /// + /// + public override bool Delete(UUID PrincipalID, string Friend) + { + return false; + } + + } +} diff --git a/OpenSim/Services/Interfaces/IFriendsService.cs b/OpenSim/Services/Interfaces/IFriendsService.cs index 0ddd5e53a9..05e85f2318 100644 --- a/OpenSim/Services/Interfaces/IFriendsService.cs +++ b/OpenSim/Services/Interfaces/IFriendsService.cs @@ -74,7 +74,7 @@ namespace OpenSim.Services.Interfaces public interface IFriendsService { FriendInfo[] GetFriends(UUID PrincipalID); - bool StoreFriend(UUID PrincipalID, string Friend, int flags); + bool StoreFriend(string PrincipalID, string Friend, int flags); bool Delete(UUID PrincipalID, string Friend); } } diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index ddc8855145..4fac951659 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -621,7 +621,19 @@ namespace OpenSim.Services.LLLoginService if (finfo.TheirFlags == -1) continue; LLLoginResponse.BuddyList.BuddyInfo buddyitem = new LLLoginResponse.BuddyList.BuddyInfo(finfo.Friend); - buddyitem.BuddyID = finfo.Friend; + // finfo.Friend may not be a simple uuid + UUID friendID = UUID.Zero; + if (UUID.TryParse(finfo.Friend, out friendID)) + buddyitem.BuddyID = finfo.Friend; + else + { + string tmp; + if (Util.ParseUniversalUserIdentifier(finfo.Friend, out friendID, out tmp, out tmp, out tmp)) + buddyitem.BuddyID = friendID.ToString(); + else + // junk entry + continue; + } buddyitem.BuddyRightsHave = (int)finfo.TheirFlags; buddyitem.BuddyRightsGiven = (int)finfo.MyFlags; buddylistreturn.AddNewBuddy(buddyitem); diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index 486f22e698..324c258c30 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -20,6 +20,7 @@ AvatarServices = "LocalAvatarServicesConnector" EntityTransferModule = "HGEntityTransferModule" InventoryAccessModule = "HGInventoryAccessModule" + FriendsModule = "HGFriendsModule" InventoryServiceInConnector = true AssetServiceInConnector = true @@ -140,6 +141,10 @@ LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGAssetService" UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" +[HGFriendsService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGFriendsService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + ;; This should always be the very last thing on this file [Includes] Include-Common = "config-include/StandaloneCommon.ini" diff --git a/prebuild.xml b/prebuild.xml index a07ad14154..1f620dc8b1 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1256,6 +1256,7 @@ + From a2c19847b4bb9b2335622bfc9757e6f7a2971c7d Mon Sep 17 00:00:00 2001 From: Kim King Date: Mon, 16 May 2011 05:57:08 -0400 Subject: [PATCH 022/186] ScriptEngine/Shared: Fix bug 5473 (v2). --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 298d664a64..461b473608 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -1536,6 +1536,7 @@ namespace OpenSim.Region.ScriptEngine.Shared public struct LSLInteger { public int value; + private static readonly Regex castRegex = new Regex(@"(^[ ]*0[xX][0-9A-Fa-f][0-9A-Fa-f]*)|(^[ ]*(-?|\+?)[0-9][0-9]*)"); #region Constructors public LSLInteger(int i) @@ -1555,9 +1556,10 @@ namespace OpenSim.Region.ScriptEngine.Shared public LSLInteger(string s) { - Regex r = new Regex("(^[ ]*0[xX][0-9A-Fa-f][0-9A-Fa-f]*)|(^[ ]*-?[0-9][0-9]*)"); - Match m = r.Match(s); + Match m = castRegex.Match(s); string v = m.Groups[0].Value; + // Leading plus sign is allowed, but ignored + v = v.Replace("+", ""); if (v == String.Empty) { From 9fc29e1595f921bda761d71da59162f31cc32799 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 20 May 2011 20:19:32 +0100 Subject: [PATCH 023/186] Implement llGetLinKNumberOfSides(). Based on code in http://opensimulator.org/mantis/view.php?id=5489 Thanks onesong. --- .../Shared/Api/Implementation/LSL_Api.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index cb3bddc780..1cf03b8f11 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4458,10 +4458,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return result; } - public void llGetLinkNumberOfSides(int link) + public LSL_Integer llGetLinkNumberOfSides(int link) { m_host.AddScriptLPS(1); - NotImplemented("llGetLinkNumberOfSides"); + + SceneObjectPart linkedPart; + + if (link == ScriptBaseClass.LINK_ROOT) + linkedPart = m_host.ParentGroup.RootPart; + else if (link == ScriptBaseClass.LINK_THIS) + linkedPart = m_host; + else + linkedPart = m_host.ParentGroup.GetLinkNumPart(link); + + return GetNumberOfSides(linkedPart); } public LSL_Integer llGetNumberOfSides() From 7ed419217fc63f7a01c13a7c3320e97edd6bb1b6 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 20 May 2011 23:22:27 +0100 Subject: [PATCH 024/186] add test for rezzing an object from a prim item --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 3 ++ .../Scenes/Tests/TaskInventoryTests.cs | 45 ++++++++++++++++++- OpenSim/Tests/Common/Setup/AssetHelpers.cs | 20 +++++++-- 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 9df73408bb..0722cee7bd 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1971,8 +1971,9 @@ namespace OpenSim.Region.Framework.Scenes /// /// Add a newly created object to the scene. /// - /// + /// /// This method does not send updates to the client - callers need to handle this themselves. + /// /// /// /// Position of the object diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index fc31b65ec6..14b587fbd1 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -344,6 +344,9 @@ namespace OpenSim.Region.Framework.Scenes /// Add an object to the scene. This will both update the scene, and send information about the /// new object to all clients interested in the scene. /// + /// + /// The object's stored position, rotation and velocity are used. + /// /// /// /// If true, the object is made persistent into the scene. diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 2aef4b0d19..73f66cba4f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -90,11 +90,54 @@ namespace OpenSim.Region.Framework.Tests return ncItem; } - + + [Test] + public void TestRezObjectFromInventoryItem() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene(); + UserAccount user1 = CreateUser(scene); + SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); + SceneObjectPart sop1 = sog1.RootPart; + + // Create an object embedded inside the first + UUID taskSceneObjectItemId = UUID.Parse("00000000-0000-0000-0000-100000000000"); + + SceneObjectGroup taskSceneObject = SceneSetupHelpers.CreateSceneObject(1, UUID.Zero); + AssetBase taskSceneObjectAsset = AssetHelpers.CreateAsset(0x10, taskSceneObject); + scene.AssetService.Store(taskSceneObjectAsset); + TaskInventoryItem taskSceneObjectItem + = new TaskInventoryItem + { Name = "tso", AssetID = taskSceneObjectAsset.FullID, ItemID = taskSceneObjectItemId, + Type = (int)AssetType.Object, InvType = (int)InventoryType.Object }; + sop1.Inventory.AddInventoryItem(taskSceneObjectItem, true); + + scene.AddSceneObject(sog1); + + Vector3 rezPos = new Vector3(10, 10, 10); + Quaternion rezRot = new Quaternion(0.5f, 0.5f, 0.5f, 0.5f); + Vector3 rezVel = new Vector3(2, 2, 2); + + scene.RezObject(sop1, taskSceneObjectItem, rezPos, rezRot, rezVel, 0); + + SceneObjectPart rezzedObjectPart = scene.GetSceneObjectPart("tso"); + + Assert.That(rezzedObjectPart, Is.Not.Null); + Assert.That(rezzedObjectPart.AbsolutePosition, Is.EqualTo(rezPos)); + Assert.That(rezzedObjectPart.RotationOffset, Is.EqualTo(rezRot)); + + // Velocity isn't being set, possibly because we have no physics + //Assert.That(rezzedObjectPart.Velocity, Is.EqualTo(rezVel)); + } + /// /// Test MoveTaskInventoryItem where the item has no parent folder assigned. /// + /// /// This should place it in the most suitable user folder. + /// [Test] public void TestMoveTaskInventoryItem() { diff --git a/OpenSim/Tests/Common/Setup/AssetHelpers.cs b/OpenSim/Tests/Common/Setup/AssetHelpers.cs index d572249997..aa55bcdc69 100644 --- a/OpenSim/Tests/Common/Setup/AssetHelpers.cs +++ b/OpenSim/Tests/Common/Setup/AssetHelpers.cs @@ -56,10 +56,24 @@ namespace OpenSim.Tests.Common AssetBase asset = CreateAsset(UUID.Random(), AssetType.Notecard, "hello", creatorId); scene.AssetService.Store(asset); return asset; - } + } + + /// + /// Create an asset from the given object. + /// + /// + /// The hexadecimal last part of the UUID for the asset created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" + /// will be used. + /// + /// + /// + public static AssetBase CreateAsset(int assetUuidTail, SceneObjectGroup sog) + { + return CreateAsset(new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", assetUuidTail)), sog); + } /// - /// Create an asset from the given scene object. + /// Create an asset from the given object. /// /// /// @@ -76,7 +90,7 @@ namespace OpenSim.Tests.Common /// /// Create an asset from the given scene object. /// - /// + /// /// The hexadecimal last part of the UUID for the asset created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" /// will be used. /// From 91a9f30b1613fba8c3ff31de5b9390b0e636ad65 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 20 May 2011 23:34:34 +0100 Subject: [PATCH 025/186] implement Scene.GetSceneObjectGroup(UUID fullID) using existing index --- OpenSim/Region/Framework/Scenes/Scene.cs | 10 ++++++++++ OpenSim/Region/Framework/Scenes/SceneGraph.cs | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0722cee7bd..f718331ec1 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4278,6 +4278,16 @@ namespace OpenSim.Region.Framework.Scenes // } // } + /// + /// Get a group via its UUID + /// + /// + /// + public SceneObjectGroup GetSceneObjectGroup(UUID fullID) + { + return m_sceneGraph.GetSceneObjectGroup(fullID); + } + /// /// Get a named prim contained in this scene (will return the first /// found, if there are more than one prim with the same name) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 14b587fbd1..2d547f7926 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -975,6 +975,22 @@ namespace OpenSim.Region.Framework.Scenes return result; } + /// + /// Get a group in the scene + /// + /// UUID of the group + /// null if no such group was found + protected internal SceneObjectGroup GetSceneObjectGroup(UUID fullID) + { + lock (SceneObjectGroupsByFullID) + { + if (SceneObjectGroupsByFullID.ContainsKey(fullID)) + return SceneObjectGroupsByFullID[fullID]; + } + + return null; + } + /// /// Get a part contained in this scene. /// From 4b0fc4faef657cc819dfa360fb6a266532724455 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 20 May 2011 23:41:14 +0100 Subject: [PATCH 026/186] implement Scene.GetSceneObjectGroup(string name) to match the equivalent GetSOP method --- OpenSim/Region/Framework/Scenes/Scene.cs | 15 +++++++-- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 31 ++++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f718331ec1..cfb3a5d7e2 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4282,14 +4282,25 @@ namespace OpenSim.Region.Framework.Scenes /// Get a group via its UUID /// /// - /// + /// null if no group with that name exists public SceneObjectGroup GetSceneObjectGroup(UUID fullID) { return m_sceneGraph.GetSceneObjectGroup(fullID); } /// - /// Get a named prim contained in this scene (will return the first + /// Get a group by name from the scene (will return the first + /// found, if there are more than one prim with the same name) + /// + /// + /// null if no group with that name exists + public SceneObjectGroup GetSceneObjectGroup(string name) + { + return m_sceneGraph.GetSceneObjectGroup(name); + } + + /// + /// Get a prim by name from the scene (will return the first /// found, if there are more than one prim with the same name) /// /// diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 2d547f7926..0cff011cf5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -991,6 +991,35 @@ namespace OpenSim.Region.Framework.Scenes return null; } + /// + /// Get a group by name from the scene (will return the first + /// found, if there are more than one prim with the same name) + /// + /// + /// null if the part was not found + protected internal SceneObjectGroup GetSceneObjectGroup(string name) + { + SceneObjectGroup so = null; + + Entities.Find( + delegate(EntityBase entity) + { + if (entity is SceneObjectGroup) + { + if (entity.Name == name) + { + so = (SceneObjectGroup)entity; + return true; + } + } + + return false; + } + ); + + return so; + } + /// /// Get a part contained in this scene. /// @@ -1005,7 +1034,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Get a named prim contained in this scene (will return the first + /// Get a prim by name from the scene (will return the first /// found, if there are more than one prim with the same name) /// /// From f2095ea2797bd01dc727cdfac052508a17f62dc0 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 20 May 2011 23:45:39 +0100 Subject: [PATCH 027/186] refactor TestRezObjectFromInventoryItem() --- .../Framework/Scenes/Tests/TaskInventoryTests.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 73f66cba4f..4d4974fd02 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -122,14 +122,14 @@ namespace OpenSim.Region.Framework.Tests scene.RezObject(sop1, taskSceneObjectItem, rezPos, rezRot, rezVel, 0); - SceneObjectPart rezzedObjectPart = scene.GetSceneObjectPart("tso"); + SceneObjectGroup rezzedObject = scene.GetSceneObjectGroup("tso"); - Assert.That(rezzedObjectPart, Is.Not.Null); - Assert.That(rezzedObjectPart.AbsolutePosition, Is.EqualTo(rezPos)); - Assert.That(rezzedObjectPart.RotationOffset, Is.EqualTo(rezRot)); + Assert.That(rezzedObject, Is.Not.Null); + Assert.That(rezzedObject.AbsolutePosition, Is.EqualTo(rezPos)); + Assert.That(rezzedObject.Velocity, Is.EqualTo(rezVel)); - // Velocity isn't being set, possibly because we have no physics - //Assert.That(rezzedObjectPart.Velocity, Is.EqualTo(rezVel)); + // Confusingly, this isn't the rezzedObject.Rotation + Assert.That(rezzedObject.RootPart.RotationOffset, Is.EqualTo(rezRot)); } /// From 90567a9eaac717ab86316c078e148f8fe13432ac Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 00:02:53 +0100 Subject: [PATCH 028/186] refactor Scene.RezObject() to use AddNewSceneObject() rather than copy/pasting code with small differences --- .../Region/Framework/Scenes/Scene.Inventory.cs | 14 +------------- OpenSim/Region/Framework/Scenes/Scene.cs | 6 +++--- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 17 +++++++++-------- .../Scenes/Tests/TaskInventoryTests.cs | 5 ++++- 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 7b88f4f439..3c4787397b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2095,19 +2095,7 @@ namespace OpenSim.Region.Framework.Scenes sourcePart.Inventory.RemoveInventoryItem(item.ItemID); } - AddNewSceneObject(group, true); - - group.AbsolutePosition = pos; - group.Velocity = vel; - - if (rot != null) - group.UpdateGroupRotationR((Quaternion)rot); - - // TODO: This needs to be refactored with the similar code in - // SceneGraph.AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) - // possibly by allowing this method to take a null rotation. - if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero) - group.RootPart.ApplyImpulse((vel * group.GetMass()), false); + AddNewSceneObject(group, true, pos, rot, vel); // We can only call this after adding the scene object, since the scene object references the scene // to find out if scripts should be activated at all. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index cfb3a5d7e2..b9690fe70b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1976,12 +1976,12 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - /// Position of the object - /// Rotation of the object + /// Position of the object. If null then the position stored in the object is used. + /// Rotation of the object. If null then the rotation stored in the object is used. /// Velocity of the object. This parameter only has an effect if the object is physical /// public bool AddNewSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) + SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) { if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel)) { diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 0cff011cf5..cdb4e412c6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -311,25 +311,26 @@ namespace OpenSim.Region.Framework.Scenes /// This method does not send updates to the client - callers need to handle this themselves. /// /// - /// Position of the object - /// Rotation of the object + /// Position of the object. If null then the position stored in the object is used. + /// Rotation of the object. If null then the rotation stored in the object is used. /// Velocity of the object. This parameter only has an effect if the object is physical /// public bool AddNewSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) + SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) { AddNewSceneObject(sceneObject, true, false); - // we set it's position in world. - sceneObject.AbsolutePosition = pos; + if (pos != null) + sceneObject.AbsolutePosition = (Vector3)pos; if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) { sceneObject.ClearPartAttachmentData(); } - - sceneObject.UpdateGroupRotationR(rot); - + + if (rot != null) + sceneObject.UpdateGroupRotationR((Quaternion)rot); + //group.ApplyPhysics(m_physicalPrim); if (sceneObject.RootPart.PhysActor != null && sceneObject.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero) { diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 4d4974fd02..222710f55d 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -126,7 +126,10 @@ namespace OpenSim.Region.Framework.Tests Assert.That(rezzedObject, Is.Not.Null); Assert.That(rezzedObject.AbsolutePosition, Is.EqualTo(rezPos)); - Assert.That(rezzedObject.Velocity, Is.EqualTo(rezVel)); + + // Velocity doesn't get applied, probably because there is no physics in tests (yet) +// Assert.That(rezzedObject.Velocity, Is.EqualTo(rezVel)); + Assert.That(rezzedObject.Velocity, Is.EqualTo(Vector3.Zero)); // Confusingly, this isn't the rezzedObject.Rotation Assert.That(rezzedObject.RootPart.RotationOffset, Is.EqualTo(rezRot)); From bc43cef5816ef5d95de153bcfe00615c5b3f79a7 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 00:05:00 +0100 Subject: [PATCH 029/186] minor: remove mono compiler warning --- .../OptionalModules/World/AutoBackup/AutoBackupModule.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs index b74d6e7c7d..ec9f1578e7 100644 --- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs +++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs @@ -278,21 +278,21 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup { string sRegionName; string sRegionLabel; - string prepend; +// string prepend; AutoBackupModuleState state; if (parseDefault) { sRegionName = null; sRegionLabel = "DEFAULT"; - prepend = ""; +// prepend = ""; state = this.m_defaultState; } else { sRegionName = scene.RegionInfo.RegionName; sRegionLabel = sRegionName; - prepend = sRegionName + "."; +// prepend = sRegionName + "."; state = null; } From 3fed61a5d5e65c36791317cec85dc130bba1cc82 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 00:07:24 +0100 Subject: [PATCH 030/186] refactor: in TaskInventoryTests, use UserProfileTestUtils.CreateUserWithInvetory() --- .../Framework/Scenes/Tests/TaskInventoryTests.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 222710f55d..4f5018a3f6 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -53,15 +53,6 @@ namespace OpenSim.Region.Framework.Tests [TestFixture] public class TaskInventoryTests { - protected UserAccount CreateUser(Scene scene) - { - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - string userPassword = "troll"; - UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - return UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); - } - protected SceneObjectGroup CreateSO1(Scene scene, UUID ownerId) { string part1Name = "part1"; @@ -98,7 +89,7 @@ namespace OpenSim.Region.Framework.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount user1 = CreateUser(scene); + UserAccount user1 = UserProfileTestUtils.CreateUserWithInventory(scene); SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; @@ -148,7 +139,7 @@ namespace OpenSim.Region.Framework.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount user1 = CreateUser(scene); + UserAccount user1 = UserProfileTestUtils.CreateUserWithInventory(scene); SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); @@ -174,7 +165,7 @@ namespace OpenSim.Region.Framework.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount user1 = CreateUser(scene); + UserAccount user1 = UserProfileTestUtils.CreateUserWithInventory(scene); SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); From 534ee52a121c209752101476e031a2c097637d82 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 00:11:52 +0100 Subject: [PATCH 031/186] rename UserProfileTestUtils to UserAccountHelpers to be consistent with other test helper names --- .../Archiver/Tests/InventoryArchiveTestCase.cs | 2 +- .../Archiver/Tests/InventoryArchiverTests.cs | 12 ++++++------ .../Avatar/Inventory/Archiver/Tests/PathTests.cs | 16 ++++++++-------- .../Tests/InventoryAccessModuleTests.cs | 2 +- .../Framework/Scenes/Tests/TaskInventoryTests.cs | 6 +++--- ...ProfileTestUtils.cs => UserAccountHelpers.cs} | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) rename OpenSim/Tests/Common/Setup/{UserProfileTestUtils.cs => UserAccountHelpers.cs} (99%) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 5ba08ee094..9421f221ab 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -104,7 +104,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, archiverModule); - UserProfileTestUtils.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); + UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); MemoryStream archiveWriteStream = new MemoryStream(); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 52232a0c9e..db57d90638 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL1, "password"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); InventoryItemBase coaItem @@ -138,7 +138,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests string userLastName = "Stirrup"; string userPassword = "troll"; UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); + UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); // Create asset UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); @@ -229,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 @@ -261,8 +261,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 @@ -294,7 +294,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaMT, "password"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password"); m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream); InventoryItemBase foundItem1 diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs index c7dae5276b..0446f3be2b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs @@ -71,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests string userLastName = "Stirrup"; string userPassword = "troll"; UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); + UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); // Create asset SceneObjectGroup object1; @@ -184,8 +184,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - UserProfileTestUtils.CreateUserWithInventory(scene, m_uaMT, "meowfood"); - UserProfileTestUtils.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); + UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "meowfood"); + UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 @@ -226,7 +226,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - UserProfileTestUtils.CreateUserWithInventory(scene, m_uaMT, "password"); + UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password"); archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/Objects", "password", m_iarStream); InventoryItemBase foundItem1 @@ -255,7 +255,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests string userFirstName = "Jock"; string userLastName = "Stirrup"; UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood"); + UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood"); // Create asset SceneObjectGroup object1; @@ -328,7 +328,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); Dictionary foldersCreated = new Dictionary(); HashSet nodesLoaded = new HashSet(); @@ -395,7 +395,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests //log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); string folder1ExistingName = "a"; string folder2Name = "b"; @@ -446,7 +446,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); string folder1ExistingName = "a"; string folder2Name = "b"; diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index 8d53cf1542..75faab0e24 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -73,7 +73,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests string userFirstName = "Jock"; string userLastName = "Stirrup"; string userPassword = "troll"; - UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, m_userId, userPassword); + UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, m_userId, userPassword); AgentCircuitData acd = new AgentCircuitData(); acd.AgentID = m_userId; diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 4f5018a3f6..e830500142 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -89,7 +89,7 @@ namespace OpenSim.Region.Framework.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount user1 = UserProfileTestUtils.CreateUserWithInventory(scene); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; @@ -139,7 +139,7 @@ namespace OpenSim.Region.Framework.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount user1 = UserProfileTestUtils.CreateUserWithInventory(scene); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); @@ -165,7 +165,7 @@ namespace OpenSim.Region.Framework.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount user1 = UserProfileTestUtils.CreateUserWithInventory(scene); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); diff --git a/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs b/OpenSim/Tests/Common/Setup/UserAccountHelpers.cs similarity index 99% rename from OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs rename to OpenSim/Tests/Common/Setup/UserAccountHelpers.cs index d01521dbdb..346f78a307 100644 --- a/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs +++ b/OpenSim/Tests/Common/Setup/UserAccountHelpers.cs @@ -36,7 +36,7 @@ namespace OpenSim.Tests.Common.Setup /// /// Utility functions for carrying out user profile related tests. /// - public static class UserProfileTestUtils + public static class UserAccountHelpers { // /// // /// Create a test user with a standard inventory From 0050bb438c7138d1deb36609faef8dcbe25348e4 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 00:15:22 +0100 Subject: [PATCH 032/186] refactor: use SceneSetupHelpers.CreateSceneObject() --- .../Framework/Scenes/Tests/TaskInventoryTests.cs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index e830500142..717517bfc2 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -53,16 +53,6 @@ namespace OpenSim.Region.Framework.Tests [TestFixture] public class TaskInventoryTests { - protected SceneObjectGroup CreateSO1(Scene scene, UUID ownerId) - { - string part1Name = "part1"; - UUID part1Id = UUID.Parse("10000000-0000-0000-0000-000000000000"); - SceneObjectPart part1 - = new SceneObjectPart(ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = part1Name, UUID = part1Id }; - return new SceneObjectGroup(part1); - } - protected TaskInventoryItem CreateSOItem1(Scene scene, SceneObjectPart part) { AssetNotecard nc = new AssetNotecard(); @@ -90,7 +80,7 @@ namespace OpenSim.Region.Framework.Tests Scene scene = SceneSetupHelpers.SetupScene(); UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); - SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); + SceneObjectGroup sog1 = SceneSetupHelpers.CreateSceneObject(1, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; // Create an object embedded inside the first @@ -140,7 +130,7 @@ namespace OpenSim.Region.Framework.Tests Scene scene = SceneSetupHelpers.SetupScene(); UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); - SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); + SceneObjectGroup sog1 = SceneSetupHelpers.CreateSceneObject(1, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); InventoryFolderBase folder @@ -166,7 +156,7 @@ namespace OpenSim.Region.Framework.Tests Scene scene = SceneSetupHelpers.SetupScene(); UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); - SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); + SceneObjectGroup sog1 = SceneSetupHelpers.CreateSceneObject(1, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); From 9103fe84d51c21d58c129fd0245c47b0a2b35c60 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 00:25:58 +0100 Subject: [PATCH 033/186] move test task inventory notecard item creation into a new TastInventoryHelpers class --- .../Scenes/Tests/TaskInventoryTests.cs | 23 +------ .../Common/Setup/TaskInventoryHelpers.cs | 68 +++++++++++++++++++ 2 files changed, 70 insertions(+), 21 deletions(-) create mode 100644 OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 717517bfc2..1c8f07898c 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -53,25 +53,6 @@ namespace OpenSim.Region.Framework.Tests [TestFixture] public class TaskInventoryTests { - protected TaskInventoryItem CreateSOItem1(Scene scene, SceneObjectPart part) - { - AssetNotecard nc = new AssetNotecard(); - nc.BodyText = "Hello World!"; - nc.Encode(); - UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); - UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); - AssetBase ncAsset - = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); - scene.AssetService.Store(ncAsset); - TaskInventoryItem ncItem - = new TaskInventoryItem - { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid, - Type = (int)AssetType.Notecard, InvType = (int)InventoryType.Notecard }; - part.Inventory.AddInventoryItem(ncItem, true); - - return ncItem; - } - [Test] public void TestRezObjectFromInventoryItem() { @@ -132,7 +113,7 @@ namespace OpenSim.Region.Framework.Tests UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); SceneObjectGroup sog1 = SceneSetupHelpers.CreateSceneObject(1, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; - TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); + TaskInventoryItem sopItem1 = TaskInventoryHelpers.AddNotecard(scene, sop1); InventoryFolderBase folder = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, user1.PrincipalID, "Objects")[0]; @@ -158,7 +139,7 @@ namespace OpenSim.Region.Framework.Tests UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); SceneObjectGroup sog1 = SceneSetupHelpers.CreateSceneObject(1, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; - TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); + TaskInventoryItem sopItem1 = TaskInventoryHelpers.AddNotecard(scene, sop1); // Perform test scene.MoveTaskInventoryItem(user1.PrincipalID, UUID.Zero, sop1, sopItem1.ItemID); diff --git a/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs b/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs new file mode 100644 index 0000000000..48724f4af4 --- /dev/null +++ b/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs @@ -0,0 +1,68 @@ +/* + * 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 OpenMetaverse; +using OpenMetaverse.Assets; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Tests.Common +{ + /// + /// Utility functions for carrying out task inventory tests. + /// + /// + public static class TaskInventoryHelpers + { + /// + /// Add a notecard item to the given part. + /// + /// + /// + /// The item that was added + public static TaskInventoryItem AddNotecard(Scene scene, SceneObjectPart part) + { + AssetNotecard nc = new AssetNotecard(); + nc.BodyText = "Hello World!"; + nc.Encode(); + UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); + UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); + AssetBase ncAsset + = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); + scene.AssetService.Store(ncAsset); + TaskInventoryItem ncItem + = new TaskInventoryItem + { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid, + Type = (int)AssetType.Notecard, InvType = (int)InventoryType.Notecard }; + part.Inventory.AddInventoryItem(ncItem, true); + + return ncItem; + } + } +} \ No newline at end of file From 084059319c125983ac43534797282ddec394cb59 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 00:37:20 +0100 Subject: [PATCH 034/186] refactor: move scene object item creation code into TaskInventoryHelpers --- .../Scenes/Tests/TaskInventoryTests.cs | 10 ++------ .../Common/Setup/TaskInventoryHelpers.cs | 23 ++++++++++++++++++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 1c8f07898c..32bb06898a 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -66,15 +66,8 @@ namespace OpenSim.Region.Framework.Tests // Create an object embedded inside the first UUID taskSceneObjectItemId = UUID.Parse("00000000-0000-0000-0000-100000000000"); - - SceneObjectGroup taskSceneObject = SceneSetupHelpers.CreateSceneObject(1, UUID.Zero); - AssetBase taskSceneObjectAsset = AssetHelpers.CreateAsset(0x10, taskSceneObject); - scene.AssetService.Store(taskSceneObjectAsset); TaskInventoryItem taskSceneObjectItem - = new TaskInventoryItem - { Name = "tso", AssetID = taskSceneObjectAsset.FullID, ItemID = taskSceneObjectItemId, - Type = (int)AssetType.Object, InvType = (int)InventoryType.Object }; - sop1.Inventory.AddInventoryItem(taskSceneObjectItem, true); + = TaskInventoryHelpers.AddSceneObjectItem(scene, sop1, "tso", taskSceneObjectItemId); scene.AddSceneObject(sog1); @@ -114,6 +107,7 @@ namespace OpenSim.Region.Framework.Tests SceneObjectGroup sog1 = SceneSetupHelpers.CreateSceneObject(1, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; TaskInventoryItem sopItem1 = TaskInventoryHelpers.AddNotecard(scene, sop1); + InventoryFolderBase folder = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, user1.PrincipalID, "Objects")[0]; diff --git a/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs b/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs index 48724f4af4..4467573569 100644 --- a/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs @@ -32,7 +32,7 @@ using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; -namespace OpenSim.Tests.Common +namespace OpenSim.Tests.Common.Setup { /// /// Utility functions for carrying out task inventory tests. @@ -64,5 +64,26 @@ namespace OpenSim.Tests.Common return ncItem; } + + /// + /// Add a scene object item to the given part. + /// + /// + /// + /// + /// + public static TaskInventoryItem AddSceneObjectItem(Scene scene, SceneObjectPart sop, string itemName, UUID id) + { + SceneObjectGroup taskSceneObject = SceneSetupHelpers.CreateSceneObject(1, UUID.Zero); + AssetBase taskSceneObjectAsset = AssetHelpers.CreateAsset(0x10, taskSceneObject); + scene.AssetService.Store(taskSceneObjectAsset); + TaskInventoryItem taskSceneObjectItem + = new TaskInventoryItem + { Name = itemName, AssetID = taskSceneObjectAsset.FullID, ItemID = id, + Type = (int)AssetType.Object, InvType = (int)InventoryType.Object }; + sop.Inventory.AddInventoryItem(taskSceneObjectItem, true); + + return taskSceneObjectItem; + } } } \ No newline at end of file From d7e5b76d73fe3e6d3a7d5506989bd2c081ab4fc6 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 00:39:42 +0100 Subject: [PATCH 035/186] refactor: rename AddSceneObjectItem to AddSceneObject --- OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs | 2 +- OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 32bb06898a..74eab6374e 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -67,7 +67,7 @@ namespace OpenSim.Region.Framework.Tests // Create an object embedded inside the first UUID taskSceneObjectItemId = UUID.Parse("00000000-0000-0000-0000-100000000000"); TaskInventoryItem taskSceneObjectItem - = TaskInventoryHelpers.AddSceneObjectItem(scene, sop1, "tso", taskSceneObjectItemId); + = TaskInventoryHelpers.AddSceneObject(scene, sop1, "tso", taskSceneObjectItemId); scene.AddSceneObject(sog1); diff --git a/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs b/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs index 4467573569..fbf00d6352 100644 --- a/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs @@ -72,7 +72,7 @@ namespace OpenSim.Tests.Common.Setup /// /// /// - public static TaskInventoryItem AddSceneObjectItem(Scene scene, SceneObjectPart sop, string itemName, UUID id) + public static TaskInventoryItem AddSceneObject(Scene scene, SceneObjectPart sop, string itemName, UUID id) { SceneObjectGroup taskSceneObject = SceneSetupHelpers.CreateSceneObject(1, UUID.Zero); AssetBase taskSceneObjectAsset = AssetHelpers.CreateAsset(0x10, taskSceneObject); From 156cc1418b38c4494d3610926c0c2b2bf6c8cc2c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 00:44:58 +0100 Subject: [PATCH 036/186] test helper rename for consistency --- ...RequestHandlerTestHelper.cs => BaseRequestHandlerHelpers.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename OpenSim/Tests/Common/Setup/{BaseRequestHandlerTestHelper.cs => BaseRequestHandlerHelpers.cs} (98%) diff --git a/OpenSim/Tests/Common/Setup/BaseRequestHandlerTestHelper.cs b/OpenSim/Tests/Common/Setup/BaseRequestHandlerHelpers.cs similarity index 98% rename from OpenSim/Tests/Common/Setup/BaseRequestHandlerTestHelper.cs rename to OpenSim/Tests/Common/Setup/BaseRequestHandlerHelpers.cs index eaf8b39ac0..286e6ff637 100644 --- a/OpenSim/Tests/Common/Setup/BaseRequestHandlerTestHelper.cs +++ b/OpenSim/Tests/Common/Setup/BaseRequestHandlerHelpers.cs @@ -36,7 +36,7 @@ using OpenSim.Tests.Common.Mock; namespace OpenSim.Tests.Common.Setup { - public class BaseRequestHandlerTestHelper + public class BaseRequestHandlerHelpers { private static string[] m_emptyStringArray = new string[] { }; From 94553d4753f092bfb25a83a5df01f277834d1088 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 00:48:01 +0100 Subject: [PATCH 037/186] rename UserInventoryTestsUtils -> UserInventoryHelpers for consistency --- .../Avatar/Inventory/Archiver/Tests/PathTests.cs | 8 ++++---- ...{UserInventoryTestUtils.cs => UserInventoryHelpers.cs} | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) rename OpenSim/Tests/Common/Setup/{UserInventoryTestUtils.cs => UserInventoryHelpers.cs} (97%) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs index 0446f3be2b..7e15a3de42 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs @@ -194,7 +194,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); // Now try loading to a root child folder - UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA"); + UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA"); MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray()); archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xA", "meowfood", archiveReadStream); @@ -203,7 +203,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); // Now try loading to a more deeply nested folder - UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC"); + UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC"); archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xB/xC", "meowfood", archiveReadStream); @@ -401,7 +401,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests string folder2Name = "b"; InventoryFolderBase folder1 - = UserInventoryTestUtils.CreateInventoryFolder( + = UserInventoryHelpers.CreateInventoryFolder( scene.InventoryService, ua1.PrincipalID, folder1ExistingName); string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); @@ -452,7 +452,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests string folder2Name = "b"; InventoryFolderBase folder1 - = UserInventoryTestUtils.CreateInventoryFolder( + = UserInventoryHelpers.CreateInventoryFolder( scene.InventoryService, ua1.PrincipalID, folder1ExistingName); string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); diff --git a/OpenSim/Tests/Common/Setup/UserInventoryTestUtils.cs b/OpenSim/Tests/Common/Setup/UserInventoryHelpers.cs similarity index 97% rename from OpenSim/Tests/Common/Setup/UserInventoryTestUtils.cs rename to OpenSim/Tests/Common/Setup/UserInventoryHelpers.cs index 135c50eb74..04191349e3 100644 --- a/OpenSim/Tests/Common/Setup/UserInventoryTestUtils.cs +++ b/OpenSim/Tests/Common/Setup/UserInventoryHelpers.cs @@ -34,9 +34,9 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Tests.Common { /// - /// Utility functions for carrying out user inventory related tests. + /// Utility functions for carrying out user inventory tests. /// - public static class UserInventoryTestUtils + public static class UserInventoryHelpers { public static readonly string PATH_DELIMITER = "/"; From 4073f1013346e206131f2f7d40508fd2bf0505d4 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 00:51:34 +0100 Subject: [PATCH 038/186] rename test helpers enclosing package from Setup to Helpers --- OpenSim/Tests/Common/{Setup => Helpers}/AssetHelpers.cs | 0 .../Tests/Common/{Setup => Helpers}/BaseRequestHandlerHelpers.cs | 0 OpenSim/Tests/Common/{Setup => Helpers}/SceneSetupHelpers.cs | 0 OpenSim/Tests/Common/{Setup => Helpers}/TaskInventoryHelpers.cs | 0 OpenSim/Tests/Common/{Setup => Helpers}/UserAccountHelpers.cs | 0 OpenSim/Tests/Common/{Setup => Helpers}/UserInventoryHelpers.cs | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename OpenSim/Tests/Common/{Setup => Helpers}/AssetHelpers.cs (100%) rename OpenSim/Tests/Common/{Setup => Helpers}/BaseRequestHandlerHelpers.cs (100%) rename OpenSim/Tests/Common/{Setup => Helpers}/SceneSetupHelpers.cs (100%) rename OpenSim/Tests/Common/{Setup => Helpers}/TaskInventoryHelpers.cs (100%) rename OpenSim/Tests/Common/{Setup => Helpers}/UserAccountHelpers.cs (100%) rename OpenSim/Tests/Common/{Setup => Helpers}/UserInventoryHelpers.cs (100%) diff --git a/OpenSim/Tests/Common/Setup/AssetHelpers.cs b/OpenSim/Tests/Common/Helpers/AssetHelpers.cs similarity index 100% rename from OpenSim/Tests/Common/Setup/AssetHelpers.cs rename to OpenSim/Tests/Common/Helpers/AssetHelpers.cs diff --git a/OpenSim/Tests/Common/Setup/BaseRequestHandlerHelpers.cs b/OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs similarity index 100% rename from OpenSim/Tests/Common/Setup/BaseRequestHandlerHelpers.cs rename to OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs similarity index 100% rename from OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs rename to OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs diff --git a/OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs similarity index 100% rename from OpenSim/Tests/Common/Setup/TaskInventoryHelpers.cs rename to OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs diff --git a/OpenSim/Tests/Common/Setup/UserAccountHelpers.cs b/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs similarity index 100% rename from OpenSim/Tests/Common/Setup/UserAccountHelpers.cs rename to OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs diff --git a/OpenSim/Tests/Common/Setup/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs similarity index 100% rename from OpenSim/Tests/Common/Setup/UserInventoryHelpers.cs rename to OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs From bb9b317f1521720a6da98c6f21735126d9c060ce Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 21 May 2011 01:05:20 +0100 Subject: [PATCH 039/186] Get rid of OpenSim.Tests.Common.Setup subpackage in favour of just OpenSim.Tests.Common instead --- OpenSim/Framework/Tests/AnimationTests.cs | 1 - .../Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs | 1 - .../Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs | 1 - .../CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs | 1 - .../InventoryAccess/Tests/InventoryAccessModuleTests.cs | 1 - .../ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs | 1 - .../Presence/Tests/PresenceConnectorsTests.cs | 1 - .../Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs | 1 - .../Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs | 1 - OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs | 1 - .../CoreModules/World/Serialiser/Tests/SerialiserTests.cs | 1 - OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs | 1 - OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs | 1 - OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs | 1 - OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs | 1 - OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs | 1 - .../Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs | 1 - .../Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs | 1 - OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs | 1 - OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs | 1 - .../Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs | 1 - OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs | 1 - OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs | 1 - .../Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs | 1 - OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs | 1 - OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs | 1 - OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs | 2 +- OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs | 2 +- OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs | 2 +- OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs | 2 +- 30 files changed, 4 insertions(+), 30 deletions(-) diff --git a/OpenSim/Framework/Tests/AnimationTests.cs b/OpenSim/Framework/Tests/AnimationTests.cs index 9aa95afa43..aa4c6aa1a7 100644 --- a/OpenSim/Framework/Tests/AnimationTests.cs +++ b/OpenSim/Framework/Tests/AnimationTests.cs @@ -33,7 +33,6 @@ using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; using Animation = OpenSim.Framework.Animation; namespace OpenSim.Framework.Tests diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 9421f221ab..aadeedb337 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -44,7 +44,6 @@ using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index db57d90638..d97311ab2b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -44,7 +44,6 @@ using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs index 7e15a3de42..127d5f81f1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs @@ -44,7 +44,6 @@ using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index 75faab0e24..733ad25843 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -45,7 +45,6 @@ using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs index 18db9fa0e3..c044407d99 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs @@ -40,7 +40,6 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid; using OpenSim.Region.Framework.Scenes; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs index e471f756d0..4556df3535 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs @@ -40,7 +40,6 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; using OpenSim.Region.Framework.Scenes; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests { diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 729e9f78bd..2eb2861005 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -43,7 +43,6 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader; using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter; diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs index 67b00ac759..a3aa38de94 100644 --- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs +++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs @@ -37,7 +37,6 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.World.Land.Tests { diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs index 5b85830f5f..d5b708229a 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs @@ -40,7 +40,6 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests { diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs index a866fd938c..4f752ab82b 100644 --- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs +++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs @@ -35,7 +35,6 @@ using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.World.Serialiser.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs index 855b5894b6..cff649b33f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs @@ -43,7 +43,6 @@ using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs index 667b74ea95..f69a4b430c 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs @@ -37,7 +37,6 @@ using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs index ca635d708d..895f2bb4ec 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs @@ -34,7 +34,6 @@ using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index a6a95ef885..0a82c4f574 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -34,7 +34,6 @@ using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs index 0d260266ef..5357a06bb6 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs @@ -37,7 +37,6 @@ using OpenSim.Region.CoreModules.World.Permissions; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs index bdfcd1dc29..cb1d531ab9 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs @@ -35,7 +35,6 @@ using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; using log4net; namespace OpenSim.Region.Framework.Scenes.Tests diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs index 8876a435b6..77bd4c2022 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs @@ -40,7 +40,6 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index efb757fa6c..03ac252967 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -44,7 +44,6 @@ using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs index abcce66e23..13d93f943f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs @@ -43,7 +43,6 @@ using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs index dd28416788..1b5a54ec3c 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs @@ -36,7 +36,6 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; using System.Threading; namespace OpenSim.Region.Framework.Scenes.Tests diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 74eab6374e..f4e14d4424 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -46,7 +46,6 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs index dbf9e0f550..4da8df135f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs @@ -33,7 +33,6 @@ using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Setup; using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.Framework.Scenes.Tests diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs index 6de97b7269..ee52a39170 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs @@ -35,7 +35,6 @@ using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests { diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs index 1d55b95f30..80b60a4976 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs @@ -29,7 +29,6 @@ using System.Collections.Generic; using NUnit.Framework; using OpenSim.Tests.Common; using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Tests.Common.Setup; using OpenSim.Region.Framework.Scenes; using Nini.Config; using OpenSim.Region.ScriptEngine.Shared.Api; diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs index 045abb4490..b635d5c604 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using Nini.Config; using NUnit.Framework; -using OpenSim.Tests.Common.Setup; using OpenSim.Tests.Common.Mock; using OpenSim.Region.Framework.Scenes; using OpenMetaverse; diff --git a/OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs b/OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs index 286e6ff637..49c99c5de4 100644 --- a/OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs @@ -34,7 +34,7 @@ using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Tests.Common.Mock; -namespace OpenSim.Tests.Common.Setup +namespace OpenSim.Tests.Common { public class BaseRequestHandlerHelpers { diff --git a/OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs index d1224099e2..bef0481edf 100644 --- a/OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs @@ -49,7 +49,7 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common.Mock; -namespace OpenSim.Tests.Common.Setup +namespace OpenSim.Tests.Common { /// /// Helpers for setting up scenes. diff --git a/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs index fbf00d6352..5215c3404d 100644 --- a/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs @@ -32,7 +32,7 @@ using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; -namespace OpenSim.Tests.Common.Setup +namespace OpenSim.Tests.Common { /// /// Utility functions for carrying out task inventory tests. diff --git a/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs b/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs index 346f78a307..8cfad79f28 100644 --- a/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs @@ -31,7 +31,7 @@ using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; -namespace OpenSim.Tests.Common.Setup +namespace OpenSim.Tests.Common { /// /// Utility functions for carrying out user profile related tests. From 58c53c41de2cae0bb041a2e8121792e136d1edb2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 21 May 2011 16:48:00 -0700 Subject: [PATCH 040/186] Fixed permissions bug related to friends in PermissionsModule. Added FriendsData[] GetFriends(string principalID) to IFriendsData and FriendInfo[] GetFriends(string PrincipalID) to IFriendsService. Refactored some more in the FriendsModule. Made client get notification of local friends permissions upon HGLogin. HG Friends object permissions work. --- OpenSim/Data/IFriendsData.cs | 1 + OpenSim/Data/MSSQL/MSSQLFriendsData.cs | 6 + OpenSim/Data/MySQL/MySQLFriendsData.cs | 5 + OpenSim/Data/Null/NullFriendsData.cs | 7 +- OpenSim/Data/SQLite/SQLiteFriendsData.cs | 7 +- .../Avatar/Friends/FriendsModule.cs | 105 ++++--- .../Avatar/Friends/HGFriendsModule.cs | 259 ++++++------------ .../World/Permissions/PermissionsModule.cs | 43 +-- .../Framework/Interfaces/IFriendsModule.cs | 2 +- .../Friends/FriendsServerPostHandler.cs | 23 +- .../Hypergrid/HGFriendsServerPostHandler.cs | 116 +++++--- .../Friends/FriendsServiceConnector.cs | 17 +- .../Hypergrid/HGFriendsServiceConnector.cs | 37 +-- .../SimianFriendsServiceConnector.cs | 18 +- OpenSim/Services/Friends/FriendsService.cs | 26 ++ .../HypergridService/HGFriendsService.cs | 4 +- .../Services/Interfaces/IFriendsService.cs | 1 + 17 files changed, 376 insertions(+), 301 deletions(-) diff --git a/OpenSim/Data/IFriendsData.cs b/OpenSim/Data/IFriendsData.cs index 4da567e56b..52e7f1419a 100644 --- a/OpenSim/Data/IFriendsData.cs +++ b/OpenSim/Data/IFriendsData.cs @@ -47,5 +47,6 @@ namespace OpenSim.Data bool Store(FriendsData data); bool Delete(UUID ownerID, string friend); FriendsData[] GetFriends(UUID principalID); + FriendsData[] GetFriends(string principalID); } } diff --git a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs index af4fd9ba55..ba1b085ef6 100644 --- a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs +++ b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs @@ -67,6 +67,11 @@ namespace OpenSim.Data.MSSQL } public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendsData[] GetFriends(string principalID) { using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) @@ -79,5 +84,6 @@ namespace OpenSim.Data.MSSQL return DoQuery(cmd); } } + } } diff --git a/OpenSim/Data/MySQL/MySQLFriendsData.cs b/OpenSim/Data/MySQL/MySQLFriendsData.cs index 663fad6603..69fac9d3f1 100644 --- a/OpenSim/Data/MySQL/MySQLFriendsData.cs +++ b/OpenSim/Data/MySQL/MySQLFriendsData.cs @@ -56,6 +56,11 @@ namespace OpenSim.Data.MySQL } public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendsData[] GetFriends(string principalID) { MySqlCommand cmd = new MySqlCommand(); diff --git a/OpenSim/Data/Null/NullFriendsData.cs b/OpenSim/Data/Null/NullFriendsData.cs index 0c69bb1700..2bfdc7a72d 100644 --- a/OpenSim/Data/Null/NullFriendsData.cs +++ b/OpenSim/Data/Null/NullFriendsData.cs @@ -42,6 +42,11 @@ namespace OpenSim.Data.Null { } + public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + /// /// Tries to implement the Get [] semantics, but it cuts corners. /// Specifically, it gets all friendships even if they weren't accepted yet. @@ -49,7 +54,7 @@ namespace OpenSim.Data.Null /// /// /// - public FriendsData[] GetFriends(UUID userID) + public FriendsData[] GetFriends(string userID) { List lst = m_Data.FindAll(delegate (FriendsData fdata) { diff --git a/OpenSim/Data/SQLite/SQLiteFriendsData.cs b/OpenSim/Data/SQLite/SQLiteFriendsData.cs index 4bfd228364..d925412dba 100644 --- a/OpenSim/Data/SQLite/SQLiteFriendsData.cs +++ b/OpenSim/Data/SQLite/SQLiteFriendsData.cs @@ -46,7 +46,12 @@ namespace OpenSim.Data.SQLite { } - public FriendsData[] GetFriends(UUID userID) + public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendsData[] GetFriends(string userID) { SqliteCommand cmd = new SqliteCommand(); diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 21cd924583..4879d20800 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - private static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0]; + protected static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0]; private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected List m_Scenes = new List(); @@ -187,6 +187,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { if (!m_Enabled) return; + m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); m_Scenes.Add(scene); scene.RegisterModuleInterface(this); @@ -221,13 +222,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion - public uint GetFriendPerms(UUID principalID, UUID friendID) + public virtual uint GetFriendPerms(UUID principalID, UUID friendID) { FriendInfo[] friends = GetFriends(principalID); - foreach (FriendInfo fi in friends) + FriendInfo finfo = GetFriend(friends, friendID); + if (finfo != null) { - if (fi.Friend == friendID.ToString()) - return (uint)fi.TheirFlags; + return (uint)finfo.TheirFlags; } return 0; @@ -241,14 +242,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.OnTerminateFriendship += OnTerminateFriendship; client.OnGrantUserRights += OnGrantUserRights; - Util.FireAndForget(delegate { FetchFriendslist(client.AgentId); }); + Util.FireAndForget(delegate { FetchFriendslist(client); }); } /// Fetch the friends list or increment the refcount for the existing /// friends list /// Returns true if the list was fetched, false if it wasn't - protected virtual bool FetchFriendslist(UUID agentID) + protected virtual bool FetchFriendslist(IClientAPI client) { + UUID agentID = client.AgentId; lock (m_Friends) { UserFriendData friendsData; @@ -261,7 +263,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { friendsData = new UserFriendData(); friendsData.PrincipalID = agentID; - friendsData.Friends = FriendsService.GetFriends(agentID); + friendsData.Friends = GetFriendsFromService(client); friendsData.Refcount = 1; m_Friends[agentID] = friendsData; @@ -270,6 +272,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } + protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client) + { + return FriendsService.GetFriends(client.AgentId); + } + private void OnClientClosed(UUID agentID, Scene scene) { ScenePresence sp = scene.GetScenePresence(agentID); @@ -293,8 +300,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnMakeRootAgent(ScenePresence sp) { - UUID agentID = sp.ControllingClient.AgentId; - UpdateFriendsCache(agentID); + UpdateFriendsCache(sp.ControllingClient); } private void OnClientLogin(IClientAPI client) @@ -309,7 +315,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_NeedsListOfFriends.Add(agentID); } - public void SendFriendsOnlineIfNeeded(IClientAPI client) + public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client) { UUID agentID = client.AgentId; @@ -317,7 +323,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends lock (m_NeedsListOfFriends) { if (!m_NeedsListOfFriends.Remove(agentID)) - return; + return false; } // Send the friends online @@ -366,6 +372,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Finally LocalFriendshipOffered(agentID, im); } + + return true; } protected virtual string FriendshipMessage(string friendID) @@ -579,7 +587,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends StoreFriendships(agentID, friendID); // Update the local cache - UpdateFriendsCache(agentID); + UpdateFriendsCache(client); // // Notify the friend @@ -647,7 +655,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends DeleteFriendship(agentID, exfriendID); // Update local cache - UpdateFriendsCache(agentID); + UpdateFriendsCache(client); client.SendTerminateFriend(exfriendID); @@ -679,23 +687,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) { + m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); + FriendInfo[] friends = GetFriends(remoteClient.AgentId); if (friends.Length == 0) - return; - - m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); - // Let's find the friend in this user's friend list - FriendInfo friend = null; - foreach (FriendInfo fi in friends) { - if (fi.Friend == target.ToString()) - friend = fi; + m_log.DebugFormat("[XXX]: agent {0} has no friends", requester); + return; } + // Let's find the friend in this user's friend list + FriendInfo friend = GetFriend(friends, target); + if (friend != null) // Found it { // Store it on the DB - FriendsService.StoreFriend(requester.ToString(), target.ToString(), rights); + if (!SimpleStore(requester, target, rights)) + { + remoteClient.SendAlertMessage("Unable to grant rights."); + return; + } // Store it in the local cache int myFlags = friend.MyFlags; @@ -725,6 +736,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } } + else + m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester); + } + + protected virtual bool SimpleStore(UUID agentID, UUID friendID, int rights) + { + FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights); + return true; + } + + protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) + { + foreach (FriendInfo fi in friends) + { + if (fi.Friend == friendID.ToString()) + return fi; + } + return null; } #region Local @@ -753,7 +782,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends friendClient.SendInstantMessage(im); // Update the local cache - UpdateFriendsCache(friendID); + UpdateFriendsCache(friendClient); // we're done return true; @@ -786,7 +815,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // the friend in this sim as root agent friendClient.SendTerminateFriend(exfriendID); // update local cache - UpdateFriendsCache(exfriendID); + UpdateFriendsCache(friendClient); // we're done return true; } @@ -816,15 +845,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } // Update local cache - lock (m_Friends) - { - FriendInfo[] friends = GetFriends(friendID); - foreach (FriendInfo finfo in friends) - { - if (finfo.Friend == userID.ToString()) - finfo.TheirFlags = rights; - } - } + UpdateLocalCache(userID, friendID, rights); return true; } @@ -866,13 +887,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return EMPTY_FRIENDS; } - private void UpdateFriendsCache(UUID agentID) + private void UpdateFriendsCache(IClientAPI client) { + UUID agentID = client.AgentId; lock (m_Friends) { UserFriendData friendsData; if (m_Friends.TryGetValue(agentID, out friendsData)) - friendsData.Friends = FriendsService.GetFriends(agentID); + friendsData.Friends = GetFriendsFromService(client); + } + } + + protected void UpdateLocalCache(UUID userID, UUID friendID, int rights) + { + // Update local cache + lock (m_Friends) + { + FriendInfo[] friends = GetFriends(friendID); + FriendInfo finfo = GetFriend(friends, userID); + finfo.TheirFlags = rights; } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index 645ecdc011..abffb94b69 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -58,129 +58,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion - //public void SendFriendsOnlineIfNeeded(IClientAPI client) - //{ - // UUID agentID = client.AgentId; - - // // Check if the online friends list is needed - // lock (m_NeedsListOfFriends) - // { - // if (!m_NeedsListOfFriends.Remove(agentID)) - // return; - // } - - // // Send the friends online - // List online = GetOnlineFriends(agentID); - // if (online.Count > 0) - // { - // m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count); - // client.SendAgentOnline(online.ToArray()); - // } - - // // Send outstanding friendship offers - // List outstanding = new List(); - // FriendInfo[] friends = GetFriends(agentID); - // foreach (FriendInfo fi in friends) - // { - // if (fi.TheirFlags == -1) - // outstanding.Add(fi.Friend); - // } - - // GridInstantMessage im = new GridInstantMessage(client.Scene, UUID.Zero, String.Empty, agentID, (byte)InstantMessageDialog.FriendshipOffered, - // "Will you be my friend?", true, Vector3.Zero); - - // foreach (string fid in outstanding) - // { - // UUID fromAgentID; - // if (!UUID.TryParse(fid, out fromAgentID)) - // continue; - - // UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID); - - // PresenceInfo presence = null; - // PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); - // if (presences != null && presences.Length > 0) - // presence = presences[0]; - // if (presence != null) - // im.offline = 0; - - // im.fromAgentID = fromAgentID.Guid; - // im.fromAgentName = account.FirstName + " " + account.LastName; - // im.offline = (byte)((presence == null) ? 1 : 0); - // im.imSessionID = im.fromAgentID; - - // // Finally - // LocalFriendshipOffered(agentID, im); - // } - //} - - //List GetOnlineFriends(UUID userID) - //{ - // List friendList = new List(); - // List online = new List(); - - // FriendInfo[] friends = GetFriends(userID); - // foreach (FriendInfo fi in friends) - // { - // if (((fi.TheirFlags & 1) != 0) && (fi.TheirFlags != -1)) - // friendList.Add(fi.Friend); - // } - - // if (friendList.Count > 0) - // { - // PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray()); - // foreach (PresenceInfo pi in presence) - // { - // UUID presenceID; - // if (UUID.TryParse(pi.UserID, out presenceID)) - // online.Add(presenceID); - // } - // } - - // return online; - //} - - //private void StatusNotify(FriendInfo friend, UUID userID, bool online) - //{ - // UUID friendID; - // if (UUID.TryParse(friend.Friend, out friendID)) - // { - // // Try local - // if (LocalStatusNotification(userID, friendID, online)) - // return; - - // // The friend is not here [as root]. Let's forward. - // PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); - // if (friendSessions != null && friendSessions.Length > 0) - // { - // PresenceInfo friendSession = null; - // foreach (PresenceInfo pinfo in friendSessions) - // if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad - // { - // friendSession = pinfo; - // break; - // } - - // if (friendSession != null) - // { - // GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - // //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); - // m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); - // } - // } - - // // Friend is not online. Ignore. - // } - // else - // { - // m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); - // } - //} - - protected override bool FetchFriendslist(UUID agentID) + protected override bool FetchFriendslist(IClientAPI client) { - if (base.FetchFriendslist(agentID)) + if (base.FetchFriendslist(client)) { + UUID agentID = client.AgentId; // We need to preload the user management cache with the names // of foreign friends, just like we do with SOPs' creators foreach (FriendInfo finfo in m_Friends[agentID].Friends) @@ -204,6 +86,39 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return false; } + public override bool SendFriendsOnlineIfNeeded(IClientAPI client) + { + if (base.SendFriendsOnlineIfNeeded(client)) + { + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId); + if (account == null) // foreign + { + FriendInfo[] friends = GetFriends(client.AgentId); + foreach (FriendInfo f in friends) + { + client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags); + } + } + } + return false; + } + + protected override FriendInfo[] GetFriendsFromService(IClientAPI client) + { + UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId); + if (account1 != null) + return base.GetFriendsFromService(client); + + // Foreigner + AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); + string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); + + FriendInfo[] finfos = FriendsService.GetFriends(agentUUI); + m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI); + return finfos; + } + + protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) { first = "Unknown"; last = "User"; @@ -249,6 +164,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return "Please confirm this friendship you made while you were away."; } + protected override bool SimpleStore(UUID agentID, UUID friendID, int rights) + { + UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID); + // Are they both local users? + if (account1 != null && account2 != null) + { + // local grid users + return base.SimpleStore(agentID, friendID, rights); + } + + if (account1 != null) + { + FriendInfo[] finfos = GetFriends(agentID); + if (finfos.Length > 0) + { + FriendInfo finfo = GetFriend(finfos, friendID); + FriendsService.StoreFriend(agentID.ToString(), finfo.Friend, rights); + return true; + } + } + if (account2 != null) + { + IClientAPI client = LocateClientObject(agentID); + if (client != null) + { + AgentCircuitData acircuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); + if (acircuit != null) + { + FriendsService.StoreFriend(Util.ProduceUserUniversalIdentifier(acircuit), friendID.ToString(), rights); + return true; + } + } + } + + return false; + + } + protected override void StoreBackwards(UUID friendID, UUID agentID) { UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); @@ -366,6 +320,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // my brain hurts now } + protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) + { + foreach (FriendInfo fi in friends) + { + if (fi.Friend.StartsWith(friendID.ToString())) + return fi; + } + return null; + } + protected override void DeleteFriendship(UUID agentID, UUID exfriendID) { base.DeleteFriendship(agentID, exfriendID); @@ -374,7 +338,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends FriendInfo[] friends = GetFriends(agentID); foreach (FriendInfo finfo in friends) { - if (finfo.Friend != exfriendID.ToString() && finfo.Friend.EndsWith(exfriendID.ToString())) + if (finfo.Friend != exfriendID.ToString() && finfo.Friend.StartsWith(exfriendID.ToString())) { FriendsService.Delete(agentID, exfriendID.ToString()); // TODO: delete the friendship on the other side @@ -383,56 +347,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - //private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) - //{ - // FriendInfo[] friends = GetFriends(remoteClient.AgentId); - // if (friends.Length == 0) - // return; - - // m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); - // // Let's find the friend in this user's friend list - // FriendInfo friend = null; - // foreach (FriendInfo fi in friends) - // { - // if (fi.Friend == target.ToString()) - // friend = fi; - // } - - // if (friend != null) // Found it - // { - // // Store it on the DB - // FriendsService.StoreFriend(requester, target.ToString(), rights); - - // // Store it in the local cache - // int myFlags = friend.MyFlags; - // friend.MyFlags = rights; - - // // Always send this back to the original client - // remoteClient.SendChangeUserRights(requester, target, rights); - - // // - // // Notify the friend - // // - - // // Try local - // if (LocalGrantRights(requester, target, myFlags, rights)) - // return; - - // PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { target.ToString() }); - // if (friendSessions != null && friendSessions.Length > 0) - // { - // PresenceInfo friendSession = friendSessions[0]; - // if (friendSession != null) - // { - // GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - // // TODO: You might want to send the delta to save the lookup - // // on the other end!! - // m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights); - // } - // } - // } - //} - - } } diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 170c35f814..d7324c6c55 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -548,18 +548,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions // libomv will moan about PrimFlags.ObjectYouOfficer being // deprecated - #pragma warning disable 0612 +#pragma warning disable 0612 objflags &= (uint) ~(PrimFlags.ObjectCopy | // Tells client you can copy the object - PrimFlags.ObjectModify | // tells client you can modify the object - PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) - PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it - PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object - PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object - PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object - PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set + PrimFlags.ObjectModify | // tells client you can modify the object + PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) + PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it + PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object + PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object + PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object + PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set ); - #pragma warning restore 0612 +#pragma warning restore 0612 // Creating the three ObjectFlags options for this method to choose from. // Customize the OwnerMask @@ -576,22 +576,27 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (m_bypassPermissions) return objectOwnerMask; - + // Object owners should be able to edit their own content if (user == objectOwner) return objectOwnerMask; - - if (IsFriendWithPerms(user, objectOwner)) - return objectOwnerMask; + if (IsFriendWithPerms(user, objectOwner)) + { + return objectOwnerMask; + } // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) + { return objectOwnerMask; + } // Admin should be able to edit anything in the sim (including admin objects) if (IsAdministrator(user)) + { return objectOwnerMask; - + } + // Users should be able to edit what is over their land. Vector3 taskPos = task.AbsolutePosition; ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); @@ -599,13 +604,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions { // Admin objects should not be editable by the above if (!IsAdministrator(objectOwner)) + { return objectOwnerMask; + } } // Group permissions if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0)) return objectGroupMask | objectEveryoneMask; - + return objectEveryoneMask; } @@ -673,7 +680,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions // // Nobody but the object owner can set permissions on an object // - if (locked && (!IsAdministrator(currentUser)) && denyOnLocked) { return false; @@ -704,6 +710,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions // Return immediately, so that the administrator can shares group objects return true; } + + // Friends with benefits should be able to edit the objects too + if (IsFriendWithPerms(currentUser, objectOwner)) + // Return immediately, so that the administrator can share objects with friends + return true; // Users should be able to edit what is over their land. ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y); diff --git a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs index 0ff7deeb30..d4a6857188 100644 --- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs @@ -34,6 +34,6 @@ namespace OpenSim.Region.Framework.Interfaces public interface IFriendsModule { uint GetFriendPerms(UUID PrincipalID, UUID FriendID); - void SendFriendsOnlineIfNeeded(IClientAPI client); + bool SendFriendsOnlineIfNeeded(IClientAPI client); } } diff --git a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs index 64002e1ada..71c3c73349 100644 --- a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs @@ -82,6 +82,9 @@ namespace OpenSim.Server.Handlers.Friends case "getfriends": return GetFriends(request); + case "getfriends_string": + return GetFriendsString(request); + case "storefriend": return StoreFriend(request); @@ -111,7 +114,25 @@ namespace OpenSim.Server.Handlers.Friends m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends"); FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); - //m_log.DebugFormat("[FRIENDS HANDLER]: neighbours for region {0}: {1}", regionID, rinfos.Count); + + return PackageFriends(finfos); + } + + byte[] GetFriendsString(Dictionary request) + { + string principalID = string.Empty; + if (request.ContainsKey("PRINCIPALID")) + principalID = request["PRINCIPALID"].ToString(); + else + m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends"); + + FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); + + return PackageFriends(finfos); + } + + private byte[] PackageFriends(FriendInfo[] finfos) + { Dictionary result = new Dictionary(); if ((finfos == null) || ((finfos != null) && (finfos.Length == 0))) diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs index 13d150265a..dde7875321 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs @@ -82,8 +82,8 @@ namespace OpenSim.Server.Handlers.Hypergrid switch (method) { - case "getfriends": - return GetFriends(request); + case "getfriendperms": + return GetFriendPerms(request); case "newfriendship": return NewFriendship(request); @@ -102,58 +102,45 @@ namespace OpenSim.Server.Handlers.Hypergrid #region Method-specific handlers - byte[] GetFriends(Dictionary request) + byte[] GetFriendPerms(Dictionary request) { + if (!VerifyServiceKey(request)) + return FailureResult(); + UUID principalID = UUID.Zero; if (request.ContainsKey("PRINCIPALID")) UUID.TryParse(request["PRINCIPALID"].ToString(), out principalID); - else - m_log.WarnFormat("[HGFRIENDS HANDLER]: no principalID in request to get friends"); - - FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); - //m_log.DebugFormat("[FRIENDS HANDLER]: neighbours for region {0}: {1}", regionID, rinfos.Count); - - Dictionary result = new Dictionary(); - if ((finfos == null) || ((finfos != null) && (finfos.Length == 0))) - result["result"] = "null"; else { - int i = 0; - foreach (FriendInfo finfo in finfos) - { - Dictionary rinfoDict = finfo.ToKeyValuePairs(); - result["friend" + i] = rinfoDict; - i++; - } + m_log.WarnFormat("[HGFRIENDS HANDLER]: no principalID in request to get friend perms"); + return FailureResult(); } - string xmlString = ServerUtils.BuildXmlResponse(result); - //m_log.DebugFormat("[FRIENDS HANDLER]: resp string: {0}", xmlString); - UTF8Encoding encoding = new UTF8Encoding(); - return encoding.GetBytes(xmlString); + UUID friendID = UUID.Zero; + if (request.ContainsKey("FRIENDID")) + UUID.TryParse(request["FRIENDID"].ToString(), out friendID); + else + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: no friendID in request to get friend perms"); + return FailureResult(); + } + string perms = "0"; + FriendInfo[] friendsInfo = m_FriendsService.GetFriends(principalID); + foreach (FriendInfo finfo in friendsInfo) + { + if (finfo.Friend.StartsWith(friendID.ToString())) + return SuccessResult(finfo.TheirFlags.ToString()); + } + + return FailureResult("Friend not found"); } byte[] NewFriendship(Dictionary request) { - if (!request.ContainsKey("KEY") || !request.ContainsKey("SESSIONID")) - { - m_log.WarnFormat("[HGFRIENDS HANDLER]: ignoring request without Key or SessionID"); + if (!VerifyServiceKey(request)) return FailureResult(); - } - string serviceKey = request["KEY"].ToString(); - string sessionStr = request["SESSIONID"].ToString(); - UUID sessionID; - UUID.TryParse(sessionStr, out sessionID); - - if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey)) - { - m_log.WarnFormat("[HGFRIENDS HANDLER]: Key {0} for session {1} did not match existing key. Ignoring request", serviceKey, sessionID); - return FailureResult(); - } - - m_log.DebugFormat("[XXX] Verification ok"); // OK, can proceed FriendInfo friend = new FriendInfo(request); @@ -172,6 +159,29 @@ namespace OpenSim.Server.Handlers.Hypergrid #region Misc + private bool VerifyServiceKey(Dictionary request) + { + if (!request.ContainsKey("KEY") || !request.ContainsKey("SESSIONID")) + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: ignoring request without Key or SessionID"); + return false; + } + + string serviceKey = request["KEY"].ToString(); + string sessionStr = request["SESSIONID"].ToString(); + UUID sessionID; + UUID.TryParse(sessionStr, out sessionID); + + if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey)) + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: Key {0} for session {1} did not match existing key. Ignoring request", serviceKey, sessionID); + return false; + } + + m_log.DebugFormat("[XXX] Verification ok"); + return true; + } + private byte[] SuccessResult() { XmlDocument doc = new XmlDocument(); @@ -194,6 +204,34 @@ namespace OpenSim.Server.Handlers.Hypergrid return DocToBytes(doc); } + private byte[] SuccessResult(string 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("Success")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Value", ""); + message.AppendChild(doc.CreateTextNode(value)); + + rootElement.AppendChild(message); + + return DocToBytes(doc); + } + + private byte[] FailureResult() { return FailureResult(String.Empty); diff --git a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs index 52b80e1ffd..d1afea22ed 100644 --- a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs @@ -84,7 +84,7 @@ namespace OpenSim.Services.Connectors.Friends #region IFriendsService - + public FriendInfo[] GetFriends(UUID PrincipalID) { Dictionary sendData = new Dictionary(); @@ -92,6 +92,21 @@ namespace OpenSim.Services.Connectors.Friends sendData["PRINCIPALID"] = PrincipalID.ToString(); sendData["METHOD"] = "getfriends"; + return GetFriends(sendData, PrincipalID.ToString()); + } + + public FriendInfo[] GetFriends(string PrincipalID) + { + Dictionary sendData = new Dictionary(); + + sendData["PRINCIPALID"] = PrincipalID; + sendData["METHOD"] = "getfriends_string"; + + return GetFriends(sendData, PrincipalID); + } + + protected FriendInfo[] GetFriends(Dictionary sendData, string PrincipalID) + { string reqString = ServerUtils.BuildQueryString(sendData); try diff --git a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs index 76f5f190a9..f8238897bf 100644 --- a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs @@ -63,12 +63,13 @@ namespace OpenSim.Services.Connectors.Hypergrid #region IFriendsService - public FriendInfo[] GetFriends(UUID PrincipalID) + public uint GetFriendPerms(UUID PrincipalID, UUID friendID) { Dictionary sendData = new Dictionary(); sendData["PRINCIPALID"] = PrincipalID.ToString(); - sendData["METHOD"] = "getfriends"; + sendData["FRIENDID"] = friendID.ToString(); + sendData["METHOD"] = "getfriendperms"; sendData["KEY"] = m_ServiceKey; sendData["SESSIONID"] = m_SessionID.ToString(); @@ -83,34 +84,14 @@ namespace OpenSim.Services.Connectors.Hypergrid { Dictionary replyData = ServerUtils.ParseXmlResponse(reply); - if (replyData != null) + if ((replyData != null) && replyData.ContainsKey("Value") && (replyData["Value"] != null)) { - if (replyData.ContainsKey("result") && (replyData["result"].ToString().ToLower() == "null")) - { - return new FriendInfo[0]; - } - - List finfos = new List(); - Dictionary.ValueCollection finfosList = replyData.Values; - //m_log.DebugFormat("[FRIENDS CONNECTOR]: get neighbours returned {0} elements", rinfosList.Count); - foreach (object f in finfosList) - { - if (f is Dictionary) - { - FriendInfo finfo = new FriendInfo((Dictionary)f); - finfos.Add(finfo); - } - else - m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriends {0} received invalid response type {1}", - PrincipalID, f.GetType()); - } - - // Success - return finfos.ToArray(); + uint perms = 0; + uint.TryParse(replyData["Value"].ToString(), out perms); + return perms; } - else - m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriends {0} received null response", + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriendPerms {0} received null response", PrincipalID); } @@ -120,7 +101,7 @@ namespace OpenSim.Services.Connectors.Hypergrid m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message); } - return new FriendInfo[0]; + return 0; } diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs index f61ab2956d..b1c34dd39b 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -77,6 +77,11 @@ namespace OpenSim.Services.Connectors.SimianGrid #region IFriendsService public FriendInfo[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendInfo[] GetFriends(string principalID) { if (String.IsNullOrEmpty(m_serverUrl)) return new FriendInfo[0]; @@ -95,7 +100,14 @@ namespace OpenSim.Services.Connectors.SimianGrid UUID friendID = friendEntry["Key"].AsUUID(); FriendInfo friend = new FriendInfo(); - friend.PrincipalID = principalID; + if (!UUID.TryParse(principalID, out friend.PrincipalID)) + { + string tmp = string.Empty; + if (!Util.ParseUniversalUserIdentifier(principalID, out friend.PrincipalID, out tmp, out tmp, out tmp)) + // bad record. ignore this entry + continue; + } + friend.Friend = friendID.ToString(); friend.MyFlags = friendEntry["Value"].AsInteger(); friend.TheirFlags = -1; @@ -174,7 +186,7 @@ namespace OpenSim.Services.Connectors.SimianGrid #endregion IFriendsService - private OSDArray GetFriended(UUID ownerID) + private OSDArray GetFriended(string ownerID) { NameValueCollection requestArgs = new NameValueCollection { @@ -195,7 +207,7 @@ namespace OpenSim.Services.Connectors.SimianGrid } } - private OSDArray GetFriendedBy(UUID ownerID) + private OSDArray GetFriendedBy(string ownerID) { NameValueCollection requestArgs = new NameValueCollection { diff --git a/OpenSim/Services/Friends/FriendsService.cs b/OpenSim/Services/Friends/FriendsService.cs index 039dc0bceb..4664cb30c0 100644 --- a/OpenSim/Services/Friends/FriendsService.cs +++ b/OpenSim/Services/Friends/FriendsService.cs @@ -63,6 +63,32 @@ namespace OpenSim.Services.Friends return info.ToArray(); } + public virtual FriendInfo[] GetFriends(string PrincipalID) + { + FriendsData[] data = m_Database.GetFriends(PrincipalID); + List info = new List(); + + foreach (FriendsData d in data) + { + FriendInfo i = new FriendInfo(); + + if (!UUID.TryParse(d.PrincipalID, out i.PrincipalID)) + { + string tmp = string.Empty; + if (!Util.ParseUniversalUserIdentifier(d.PrincipalID, out i.PrincipalID, out tmp, out tmp, out tmp)) + // bad record. ignore this entry + continue; + } + i.Friend = d.Friend; + i.MyFlags = Convert.ToInt32(d.Data["Flags"]); + i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]); + + info.Add(i); + } + + return info.ToArray(); + } + public virtual bool StoreFriend(string PrincipalID, string Friend, int flags) { FriendsData d = new FriendsData(); diff --git a/OpenSim/Services/HypergridService/HGFriendsService.cs b/OpenSim/Services/HypergridService/HGFriendsService.cs index fa4ec5d7ec..3ffe88973a 100644 --- a/OpenSim/Services/HypergridService/HGFriendsService.cs +++ b/OpenSim/Services/HypergridService/HGFriendsService.cs @@ -62,7 +62,7 @@ namespace OpenSim.Services.HypergridService UUID userID; if (UUID.TryParse(PrincipalID, out userID)) { - FriendsData[] friendsData = m_Database.GetFriends(userID); + FriendsData[] friendsData = m_Database.GetFriends(userID.ToString()); List fList = new List(friendsData); if (fList.Find(delegate(FriendsData fdata) { @@ -70,6 +70,8 @@ namespace OpenSim.Services.HypergridService }) != null) return false; } + else + return false; FriendsData d = new FriendsData(); d.PrincipalID = PrincipalID; diff --git a/OpenSim/Services/Interfaces/IFriendsService.cs b/OpenSim/Services/Interfaces/IFriendsService.cs index 05e85f2318..0a8efad11a 100644 --- a/OpenSim/Services/Interfaces/IFriendsService.cs +++ b/OpenSim/Services/Interfaces/IFriendsService.cs @@ -74,6 +74,7 @@ namespace OpenSim.Services.Interfaces public interface IFriendsService { FriendInfo[] GetFriends(UUID PrincipalID); + FriendInfo[] GetFriends(string PrincipalID); bool StoreFriend(string PrincipalID, string Friend, int flags); bool Delete(UUID PrincipalID, string Friend); } From dc95e38e42dbc2d1386375a2ff70341f4a92be94 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sun, 22 May 2011 14:59:18 -0400 Subject: [PATCH 041/186] Add stubs for unimplemented lsl functions --- .../Shared/Api/Implementation/LSL_Api.cs | 85 +++++++++++++++---- 1 file changed, 67 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1cf03b8f11..e3d0dac208 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3316,12 +3316,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return m_ScriptEngine.GetStartParameter(m_itemID); } - public void llGodLikeRezObject(string inventory, LSL_Vector pos) - { - m_host.AddScriptLPS(1); - NotImplemented("llGodLikeRezObject"); - } - public void llRequestPermissions(string agent, int perm) { UUID agentID = new UUID(); @@ -4189,12 +4183,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.CollisionSoundVolume = (float)impact_volume; } - public void llCollisionSprite(string impact_sprite) - { - m_host.AddScriptLPS(1); - NotImplemented("llCollisionSprite"); - } - public LSL_String llGetAnimation(string id) { // This should only return a value if the avatar is in the same region @@ -5526,12 +5514,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(100); } - public void llSetSoundQueueing(int queue) - { - m_host.AddScriptLPS(1); - NotImplemented("llSetSoundQueueing"); - } - public void llSetSoundRadius(double radius) { m_host.AddScriptLPS(1); @@ -10312,6 +10294,73 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return rq.ToString(); } + + #region Not Implemented + // + // Listing the unimplemented lsl functions here, please move + // them from this region as they are completed + // + public void llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) + { + m_host.AddScriptLPS(1); + NotImplemented("llCastRay"); + + } + + public void llGetEnv(LSL_String name) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetEnv"); + + } + + public void llGetSPMaxMemory() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetSPMaxMemory"); + + } + + public void llGetUsedMemory() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetUsedMemory"); + + } + + public void llRegionSayTo( LSL_Key target, LSL_Integer channel, LSL_String msg ) + { + m_host.AddScriptLPS(1); + NotImplemented("llRegionSayTo"); + + } + + public void llScriptProfiler( LSL_Integer flags ) + { + m_host.AddScriptLPS(1); + NotImplemented("llScriptProfiler"); + + } + + public void llSetSoundQueueing(int queue) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetSoundQueueing"); + } + + public void llCollisionSprite(string impact_sprite) + { + m_host.AddScriptLPS(1); + NotImplemented("llCollisionSprite"); + } + + public void llGodLikeRezObject(string inventory, LSL_Vector pos) + { + m_host.AddScriptLPS(1); + NotImplemented("llGodLikeRezObject"); + } + + #endregion } public class NotecardCache From fed3cc630efd223866ab03b904dc1053c2d28fe2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 22 May 2011 15:35:40 -0700 Subject: [PATCH 042/186] File to be removed --- OpenSim/Services/HypergridService/HGFriendsService.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/OpenSim/Services/HypergridService/HGFriendsService.cs b/OpenSim/Services/HypergridService/HGFriendsService.cs index 3ffe88973a..1829ae3116 100644 --- a/OpenSim/Services/HypergridService/HGFriendsService.cs +++ b/OpenSim/Services/HypergridService/HGFriendsService.cs @@ -82,16 +82,5 @@ namespace OpenSim.Services.HypergridService return m_Database.Store(d); } - /// - /// Overrides base. Cannot delete friendships while away from home. - /// - /// - /// - /// - public override bool Delete(UUID PrincipalID, string Friend) - { - return false; - } - } } From 336665e03532cf9d7a1ad65d5071e7050bf6ecd0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 22 May 2011 16:51:03 -0700 Subject: [PATCH 043/186] More on HG Friends. Added Delete(string, string) across the board. Added security to friendship identifiers so that they can safely be deleted across worlds. Had to change Get(string) to use LIKE because the secret in the identifier is not always known -- affects only HG visitors. BOTTOM LINE SO FAR: HG friendships established and deleted safely across grids, local rights working but not (yet?) being transmitted back. --- OpenSim/Data/IFriendsData.cs | 1 + OpenSim/Data/MSSQL/MSSQLFriendsData.cs | 5 + OpenSim/Data/MySQL/MySQLFriendsData.cs | 19 +- OpenSim/Data/Null/NullFriendsData.cs | 7 +- OpenSim/Data/SQLite/SQLiteFriendsData.cs | 5 + OpenSim/Framework/Util.cs | 6 +- .../Avatar/Friends/FriendsModule.cs | 111 +++++---- .../Avatar/Friends/HGFriendsModule.cs | 220 ++++++++++++------ .../Friends/FriendsServerPostHandler.cs | 23 +- .../Hypergrid/HGFriendsServerPostHandler.cs | 43 +++- .../Friends/FriendsServiceConnector.cs | 15 ++ .../Hypergrid/HGFriendsServiceConnector.cs | 50 ++++ .../SimianFriendsServiceConnector.cs | 7 +- OpenSim/Services/Friends/FriendsService.cs | 7 +- .../HypergridService/HGFriendsService.cs | 86 ------- .../Services/Interfaces/IFriendsService.cs | 1 + .../LLLoginService/LLLoginResponse.cs | 2 +- bin/config-include/StandaloneHypergrid.ini | 2 +- 18 files changed, 396 insertions(+), 214 deletions(-) delete mode 100644 OpenSim/Services/HypergridService/HGFriendsService.cs diff --git a/OpenSim/Data/IFriendsData.cs b/OpenSim/Data/IFriendsData.cs index 52e7f1419a..3fdf87b51a 100644 --- a/OpenSim/Data/IFriendsData.cs +++ b/OpenSim/Data/IFriendsData.cs @@ -46,6 +46,7 @@ namespace OpenSim.Data { bool Store(FriendsData data); bool Delete(UUID ownerID, string friend); + bool Delete(string ownerID, string friend); FriendsData[] GetFriends(UUID principalID); FriendsData[] GetFriends(string principalID); } diff --git a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs index ba1b085ef6..0b178f14cc 100644 --- a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs +++ b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs @@ -51,6 +51,11 @@ namespace OpenSim.Data.MSSQL } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) diff --git a/OpenSim/Data/MySQL/MySQLFriendsData.cs b/OpenSim/Data/MySQL/MySQLFriendsData.cs index 69fac9d3f1..130ba5e9c2 100644 --- a/OpenSim/Data/MySQL/MySQLFriendsData.cs +++ b/OpenSim/Data/MySQL/MySQLFriendsData.cs @@ -43,6 +43,11 @@ namespace OpenSim.Data.MySQL } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { MySqlCommand cmd = new MySqlCommand(); @@ -56,11 +61,6 @@ namespace OpenSim.Data.MySQL } public FriendsData[] GetFriends(UUID principalID) - { - return GetFriends(principalID.ToString()); - } - - public FriendsData[] GetFriends(string principalID) { MySqlCommand cmd = new MySqlCommand(); @@ -69,5 +69,14 @@ namespace OpenSim.Data.MySQL return DoQuery(cmd); } + + public FriendsData[] GetFriends(string principalID) + { + MySqlCommand cmd = new MySqlCommand(); + + cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID LIKE ?PrincipalID", m_Realm); + cmd.Parameters.AddWithValue("?PrincipalID", principalID.ToString() + '%'); + return DoQuery(cmd); + } } } diff --git a/OpenSim/Data/Null/NullFriendsData.cs b/OpenSim/Data/Null/NullFriendsData.cs index 2bfdc7a72d..d90788a111 100644 --- a/OpenSim/Data/Null/NullFriendsData.cs +++ b/OpenSim/Data/Null/NullFriendsData.cs @@ -77,7 +77,12 @@ namespace OpenSim.Data.Null return true; } - public bool Delete(UUID userID, string friendID) + public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string userID, string friendID) { List lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID.ToString(); }); if (lst != null) diff --git a/OpenSim/Data/SQLite/SQLiteFriendsData.cs b/OpenSim/Data/SQLite/SQLiteFriendsData.cs index d925412dba..b14c3482bb 100644 --- a/OpenSim/Data/SQLite/SQLiteFriendsData.cs +++ b/OpenSim/Data/SQLite/SQLiteFriendsData.cs @@ -63,6 +63,11 @@ namespace OpenSim.Data.SQLite } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { SqliteCommand cmd = new SqliteCommand(); diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index af21cb55cc..e5ff27a6d8 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1703,9 +1703,9 @@ namespace OpenSim.Framework /// /// /// - public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname) + public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) { - uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; + uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; string[] parts = value.Split(';'); if (parts.Length >= 1) @@ -1724,6 +1724,8 @@ namespace OpenSim.Framework lastname = name[1]; } } + if (parts.Length >= 4) + secret = parts[3]; return true; } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 4879d20800..7d948136f1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -272,11 +272,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client) - { - return FriendsService.GetFriends(client.AgentId); - } - private void OnClientClosed(UUID agentID, Scene scene) { ScenePresence sp = scene.GetScenePresence(agentID); @@ -300,7 +295,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnMakeRootAgent(ScenePresence sp) { - UpdateFriendsCache(sp.ControllingClient); + RefetchFriends(sp.ControllingClient); } private void OnClientLogin(IClientAPI client) @@ -544,11 +539,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - protected virtual void StoreBackwards(UUID friendID, UUID agentID) - { - FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0); - } - private void ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im) { // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID) @@ -587,7 +577,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends StoreFriendships(agentID, friendID); // Update the local cache - UpdateFriendsCache(client); + RefetchFriends(client); // // Notify the friend @@ -614,18 +604,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - protected virtual void StoreFriendships(UUID agentID, UUID friendID) - { - FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), 1); - FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 1); - } - private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) { m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID); - FriendsService.Delete(agentID, friendID.ToString()); - FriendsService.Delete(friendID, agentID.ToString()); + DeleteFriendship(agentID, friendID); // // Notify the friend @@ -652,10 +635,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) { - DeleteFriendship(agentID, exfriendID); + if (!DeleteFriendship(agentID, exfriendID)) + client.SendAlertMessage("Unable to terminate friendship on this sim."); // Update local cache - UpdateFriendsCache(client); + RefetchFriends(client); client.SendTerminateFriend(exfriendID); @@ -679,12 +663,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - protected virtual void DeleteFriendship(UUID agentID, UUID exfriendID) - { - FriendsService.Delete(agentID, exfriendID.ToString()); - FriendsService.Delete(exfriendID, agentID.ToString()); - } - private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) { m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); @@ -702,7 +680,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (friend != null) // Found it { // Store it on the DB - if (!SimpleStore(requester, target, rights)) + if (!StoreRights(requester, target, rights)) { remoteClient.SendAlertMessage("Unable to grant rights."); return; @@ -740,12 +718,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester); } - protected virtual bool SimpleStore(UUID agentID, UUID friendID, int rights) - { - FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights); - return true; - } - protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) { foreach (FriendInfo fi in friends) @@ -782,7 +754,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends friendClient.SendInstantMessage(im); // Update the local cache - UpdateFriendsCache(friendClient); + RefetchFriends(friendClient); // we're done return true; @@ -815,7 +787,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // the friend in this sim as root agent friendClient.SendTerminateFriend(exfriendID); // update local cache - UpdateFriendsCache(friendClient); + RefetchFriends(friendClient); // we're done return true; } @@ -874,6 +846,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion + #region Get / Set friends in several flavours + /// + /// Get friends from local cache only + /// + /// + /// protected FriendInfo[] GetFriends(UUID agentID) { UserFriendData friendsData; @@ -887,17 +865,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return EMPTY_FRIENDS; } - private void UpdateFriendsCache(IClientAPI client) - { - UUID agentID = client.AgentId; - lock (m_Friends) - { - UserFriendData friendsData; - if (m_Friends.TryGetValue(agentID, out friendsData)) - friendsData.Friends = GetFriendsFromService(client); - } - } - + /// + /// Update loca cache only + /// + /// + /// + /// protected void UpdateLocalCache(UUID userID, UUID friendID, int rights) { // Update local cache @@ -908,5 +881,47 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends finfo.TheirFlags = rights; } } + + protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client) + { + return FriendsService.GetFriends(client.AgentId); + } + + private void RefetchFriends(IClientAPI client) + { + UUID agentID = client.AgentId; + lock (m_Friends) + { + UserFriendData friendsData; + if (m_Friends.TryGetValue(agentID, out friendsData)) + friendsData.Friends = GetFriendsFromService(client); + } + } + + protected virtual bool StoreRights(UUID agentID, UUID friendID, int rights) + { + FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights); + return true; + } + + protected virtual void StoreBackwards(UUID friendID, UUID agentID) + { + FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0); + } + + protected virtual void StoreFriendships(UUID agentID, UUID friendID) + { + FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), 1); + FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 1); + } + + protected virtual bool DeleteFriendship(UUID agentID, UUID exfriendID) + { + FriendsService.Delete(agentID, exfriendID.ToString()); + FriendsService.Delete(exfriendID, agentID.ToString()); + return true; + } + + #endregion } } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index abffb94b69..c55839f20b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -72,8 +72,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends UUID id; if (!UUID.TryParse(finfo.Friend, out id)) { - string url = string.Empty, first = string.Empty, last = string.Empty; - if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last)) + string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp)) { IUserManagement uMan = m_Scenes[0].RequestModuleInterface(); uMan.AddUser(id, url + ";" + first + " " + last); @@ -103,22 +103,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return false; } - protected override FriendInfo[] GetFriendsFromService(IClientAPI client) - { - UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId); - if (account1 != null) - return base.GetFriendsFromService(client); - - // Foreigner - AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); - string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); - - FriendInfo[] finfos = FriendsService.GetFriends(agentUUI); - m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI); - return finfos; - } - - protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) { first = "Unknown"; last = "User"; @@ -126,8 +110,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return true; // fid is not a UUID... - string url = string.Empty; - if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last)) + string url = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last, out tmp)) { IUserManagement userMan = m_Scenes[0].RequestModuleInterface(); userMan.AddUser(agentID, url + ";" + first + " " + last); @@ -164,7 +148,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return "Please confirm this friendship you made while you were away."; } - protected override bool SimpleStore(UUID agentID, UUID friendID, int rights) + protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) + { + foreach (FriendInfo fi in friends) + { + if (fi.Friend.StartsWith(friendID.ToString())) + return fi; + } + return null; + } + + + protected override FriendInfo[] GetFriendsFromService(IClientAPI client) + { + UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId); + if (account1 != null) + return base.GetFriendsFromService(client); + + FriendInfo[] finfos = new FriendInfo[0]; + // Foreigner + AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); + if (agentClientCircuit != null) + { + string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); + + m_log.DebugFormat("[XXX] GetFriendsFromService to {0}", agentUUI); + finfos = FriendsService.GetFriends(agentUUI); + m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI); + } + return finfos; + } + + protected override bool StoreRights(UUID agentID, UUID friendID, int rights) { UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID); @@ -172,30 +187,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (account1 != null && account2 != null) { // local grid users - return base.SimpleStore(agentID, friendID, rights); + return base.StoreRights(agentID, friendID, rights); } - if (account1 != null) + if (account1 != null) // agent is local, friend is foreigner { FriendInfo[] finfos = GetFriends(agentID); - if (finfos.Length > 0) + FriendInfo finfo = GetFriend(finfos, friendID); + if (finfo != null) { - FriendInfo finfo = GetFriend(finfos, friendID); FriendsService.StoreFriend(agentID.ToString(), finfo.Friend, rights); return true; } } - if (account2 != null) + + if (account2 != null) // agent is foreigner, friend is local { - IClientAPI client = LocateClientObject(agentID); - if (client != null) + string agentUUI = GetUUI(friendID, agentID); + if (agentUUI != string.Empty) { - AgentCircuitData acircuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); - if (acircuit != null) - { - FriendsService.StoreFriend(Util.ProduceUserUniversalIdentifier(acircuit), friendID.ToString(), rights); - return true; - } + FriendsService.StoreFriend(agentUUI, friendID.ToString(), rights); + return true; } } @@ -233,7 +245,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return; } - // ok, at least one of them is foreigner, let's get their data IClientAPI agentClient = LocateClientObject(agentID); IClientAPI friendClient = LocateClientObject(friendID); @@ -257,13 +268,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); } - m_log.DebugFormat("[XXX] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}", + m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}", agentUUI, friendUUI, agentFriendService, friendFriendService); + // Generate a random 8-character hex number that will sign this friendship + string secret = UUID.Random().ToString().Substring(0, 8); + if (agentAccount != null) // agent is local, 'friend' is foreigner { // This may happen when the agent returned home, in which case the friend is not there - // We need to llok for its information in the friends list itself + // We need to look for its information in the friends list itself + bool confirming = false; if (friendUUI == string.Empty) { FriendInfo[] finfos = GetFriends(agentID); @@ -272,35 +287,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (finfo.TheirFlags == -1) { if (finfo.Friend.StartsWith(friendID.ToString())) + { friendUUI = finfo.Friend; + confirming = true; + } } } } - // store in the local friends service a reference to the foreign friend - FriendsService.StoreFriend(agentID.ToString(), friendUUI, 1); - // and also the converse - FriendsService.StoreFriend(friendUUI, agentID.ToString(), 1); + // If it's confirming the friendship, we already have the full friendUUI with the secret + string theFriendUUID = confirming ? friendUUI : friendUUI + ";" + secret; - if (friendClientCircuit != null) + // store in the local friends service a reference to the foreign friend + FriendsService.StoreFriend(agentID.ToString(), theFriendUUID, 1); + // and also the converse + FriendsService.StoreFriend(theFriendUUID, agentID.ToString(), 1); + + if (!confirming && friendClientCircuit != null) { // store in the foreign friends service a reference to the local agent HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID); - friendsConn.NewFriendship(friendID, agentUUI); + friendsConn.NewFriendship(friendID, agentUUI + ";" + secret); } } else if (friendAccount != null) // 'friend' is local, agent is foreigner { // store in the local friends service a reference to the foreign agent - FriendsService.StoreFriend(friendID.ToString(), agentUUI, 1); + FriendsService.StoreFriend(friendID.ToString(), agentUUI + ";" + secret, 1); // and also the converse - FriendsService.StoreFriend(agentUUI, friendID.ToString(), 1); + FriendsService.StoreFriend(agentUUI + ";" + secret, friendID.ToString(), 1); if (agentClientCircuit != null) { // store in the foreign friends service a reference to the local agent HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID); - friendsConn.NewFriendship(agentID, friendUUI); + friendsConn.NewFriendship(agentID, friendUUI + ";" + secret); } } else // They're both foreigners! @@ -309,43 +330,112 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (agentClientCircuit != null) { friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID); - friendsConn.NewFriendship(agentID, friendUUI); + friendsConn.NewFriendship(agentID, friendUUI + ";" + secret); } if (friendClientCircuit != null) { friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID); - friendsConn.NewFriendship(friendID, agentUUI); + friendsConn.NewFriendship(friendID, agentUUI + ";" + secret); } } // my brain hurts now } - protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) + protected override bool DeleteFriendship(UUID agentID, UUID exfriendID) { - foreach (FriendInfo fi in friends) + UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, exfriendID); + // Are they both local users? + if (agentAccount != null && friendAccount != null) { - if (fi.Friend.StartsWith(friendID.ToString())) - return fi; + // local grid users + return base.DeleteFriendship(agentID, exfriendID); } - return null; - } - protected override void DeleteFriendship(UUID agentID, UUID exfriendID) - { - base.DeleteFriendship(agentID, exfriendID); - // Maybe some of the base deletes will fail. - // Let's delete the local friendship with foreign friend - FriendInfo[] friends = GetFriends(agentID); - foreach (FriendInfo finfo in friends) + // ok, at least one of them is foreigner, let's get their data + string agentUUI = string.Empty; + string friendUUI = string.Empty; + + if (agentAccount != null) // agent is local, 'friend' is foreigner { - if (finfo.Friend != exfriendID.ToString() && finfo.Friend.StartsWith(exfriendID.ToString())) + // We need to look for its information in the friends list itself + FriendInfo[] finfos = GetFriends(agentID); + FriendInfo finfo = GetFriend(finfos, exfriendID); + if (finfo != null) { - FriendsService.Delete(agentID, exfriendID.ToString()); - // TODO: delete the friendship on the other side - // Should use the homeurl given in finfo.Friend + friendUUI = finfo.Friend; + + // delete in the local friends service the reference to the foreign friend + FriendsService.Delete(agentID, friendUUI); + // and also the converse + FriendsService.Delete(friendUUI, agentID.ToString()); + + // notify the exfriend's service + Util.FireAndForget(delegate { Delete(exfriendID, agentID, friendUUI); }); + + m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentID, friendUUI); + return true; } } + else if (friendAccount != null) // agent is foreigner, 'friend' is local + { + agentUUI = GetUUI(exfriendID, agentID); + + if (agentUUI != string.Empty) + { + // delete in the local friends service the reference to the foreign agent + FriendsService.Delete(exfriendID, agentUUI); + // and also the converse + FriendsService.Delete(agentUUI, exfriendID.ToString()); + + // notify the agent's service? + Util.FireAndForget(delegate { Delete(agentID, exfriendID, agentUUI); }); + + m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentUUI, exfriendID); + return true; + } + } + //else They're both foreigners! Can't handle this + + return false; } + private string GetUUI(UUID localUser, UUID foreignUser) + { + // Let's see if the user is here by any chance + FriendInfo[] finfos = GetFriends(localUser); + if (finfos != EMPTY_FRIENDS) // friend is here, cool + { + FriendInfo finfo = GetFriend(finfos, foreignUser); + if (finfo != null) + { + return finfo.Friend; + } + } + else // user is not currently on this sim, need to get from the service + { + finfos = FriendsService.GetFriends(localUser); + foreach (FriendInfo finfo in finfos) + { + if (finfo.Friend.StartsWith(foreignUser.ToString())) // found it! + { + return finfo.Friend; + } + } + } + return string.Empty; + } + + private void Delete(UUID foreignUser, UUID localUser, string uui) + { + UUID id; + string url = string.Empty, secret = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(uui, out id, out url, out tmp, out tmp, out secret)) + { + m_log.DebugFormat("[HGFRIENDS MODULE]: Deleting friendship from {0}", url); + HGFriendsServicesConnector friendConn = new HGFriendsServicesConnector(url); + friendConn.DeleteFriendship(foreignUser, localUser, secret); + } + } } } diff --git a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs index 71c3c73349..9969086a90 100644 --- a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs @@ -91,6 +91,9 @@ namespace OpenSim.Server.Handlers.Friends case "deletefriend": return DeleteFriend(request); + case "deletefriend_string": + return DeleteFriendString(request); + } m_log.DebugFormat("[FRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method); } @@ -184,7 +187,25 @@ namespace OpenSim.Server.Handlers.Friends else return FailureResult(); } - + + byte[] DeleteFriendString(Dictionary request) + { + string principalID = string.Empty; + if (request.ContainsKey("PRINCIPALID")) + principalID = request["PRINCIPALID"].ToString(); + else + m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to delete friend"); + string friend = string.Empty; + if (request.ContainsKey("FRIEND")) + friend = request["FRIEND"].ToString(); + + bool success = m_FriendsService.Delete(principalID, friend); + if (success) + return SuccessResult(); + else + return FailureResult(); + } + #endregion #region Misc diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs index dde7875321..a83d0e8b44 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs @@ -88,6 +88,8 @@ namespace OpenSim.Server.Handlers.Hypergrid case "newfriendship": return NewFriendship(request); + case "deletefriendship": + return DeleteFriendship(request); } m_log.DebugFormat("[HGFRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method); } @@ -143,11 +145,21 @@ namespace OpenSim.Server.Handlers.Hypergrid // OK, can proceed FriendInfo friend = new FriendInfo(request); + UUID friendID; + string tmp = string.Empty; + if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp)) + return FailureResult(); + + m_log.DebugFormat("[HGFRIENDS HANDLER]: New friendship {0} {1}", friend.PrincipalID, friend.Friend); + + // If the friendship already exists, return fail + FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID); + foreach (FriendInfo finfo in finfos) + if (finfo.Friend.StartsWith(friendID.ToString())) + return FailureResult(); // the user needs to confirm when he gets home bool success = m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 0); - //if (success) - // m_FriendsService.StoreFriend(friend.Friend, friend.PrincipalID.ToString(), 1); if (success) return SuccessResult(); @@ -155,6 +167,33 @@ namespace OpenSim.Server.Handlers.Hypergrid return FailureResult(); } + byte[] DeleteFriendship(Dictionary request) + { + FriendInfo friend = new FriendInfo(request); + string secret = string.Empty; + if (request.ContainsKey("SECRET")) + secret = request["SECRET"].ToString(); + + if (secret == string.Empty) + return FailureResult(); + + FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID); + foreach (FriendInfo finfo in finfos) + { + // We check the secret here + if (finfo.Friend.StartsWith(friend.Friend) && finfo.Friend.EndsWith(secret)) + { + m_log.DebugFormat("[HGFRIENDS HANDLER]: Delete friendship {0} {1}", friend.PrincipalID, friend.Friend); + m_FriendsService.Delete(friend.PrincipalID, finfo.Friend); + m_FriendsService.Delete(finfo.Friend, friend.PrincipalID.ToString()); + + return SuccessResult(); + } + } + + return FailureResult(); + } + #endregion #region Misc diff --git a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs index d1afea22ed..08f1dc3133 100644 --- a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs @@ -211,6 +211,16 @@ namespace OpenSim.Services.Connectors.Friends } + public bool Delete(string PrincipalID, string Friend) + { + Dictionary sendData = new Dictionary(); + sendData["PRINCIPALID"] = PrincipalID.ToString(); + sendData["FRIEND"] = Friend; + sendData["METHOD"] = "deletefriend_string"; + + return Delete(sendData, PrincipalID, Friend); + } + public bool Delete(UUID PrincipalID, string Friend) { Dictionary sendData = new Dictionary(); @@ -218,6 +228,11 @@ namespace OpenSim.Services.Connectors.Friends sendData["FRIEND"] = Friend; sendData["METHOD"] = "deletefriend"; + return Delete(sendData, PrincipalID.ToString(), Friend); + } + + public bool Delete(Dictionary sendData, string PrincipalID, string Friend) + { string reply = string.Empty; try { diff --git a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs index f8238897bf..d699f596a2 100644 --- a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs @@ -54,6 +54,11 @@ namespace OpenSim.Services.Connectors.Hypergrid { } + public HGFriendsServicesConnector(string serverURI) + { + m_ServerURI = serverURI.TrimEnd('/'); + } + public HGFriendsServicesConnector(string serverURI, UUID sessionID, string serviceKey) { m_ServerURI = serverURI.TrimEnd('/'); @@ -151,6 +156,51 @@ namespace OpenSim.Services.Connectors.Hypergrid } + public bool DeleteFriendship(UUID PrincipalID, UUID Friend, string secret) + { + FriendInfo finfo = new FriendInfo(); + finfo.PrincipalID = PrincipalID; + finfo.Friend = Friend.ToString(); + + Dictionary sendData = finfo.ToKeyValuePairs(); + + sendData["METHOD"] = "deletefriendship"; + sendData["SECRET"] = secret; + + string reply = string.Empty; + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/hgfriends", + ServerUtils.BuildQueryString(sendData)); + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message); + return false; + } + + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null)) + { + bool success = false; + Boolean.TryParse(replyData["Result"].ToString(), out success); + return success; + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Delete {0} {1} received null response", + PrincipalID, Friend); + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: DeleteFriend received null reply"); + + return false; + + } + #endregion } } \ No newline at end of file diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs index b1c34dd39b..7422d94b44 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -103,7 +103,7 @@ namespace OpenSim.Services.Connectors.SimianGrid if (!UUID.TryParse(principalID, out friend.PrincipalID)) { string tmp = string.Empty; - if (!Util.ParseUniversalUserIdentifier(principalID, out friend.PrincipalID, out tmp, out tmp, out tmp)) + if (!Util.ParseUniversalUserIdentifier(principalID, out friend.PrincipalID, out tmp, out tmp, out tmp, out tmp)) // bad record. ignore this entry continue; } @@ -163,6 +163,11 @@ namespace OpenSim.Services.Connectors.SimianGrid } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { if (String.IsNullOrEmpty(m_serverUrl)) return true; diff --git a/OpenSim/Services/Friends/FriendsService.cs b/OpenSim/Services/Friends/FriendsService.cs index 4664cb30c0..e2033ac93d 100644 --- a/OpenSim/Services/Friends/FriendsService.cs +++ b/OpenSim/Services/Friends/FriendsService.cs @@ -75,7 +75,7 @@ namespace OpenSim.Services.Friends if (!UUID.TryParse(d.PrincipalID, out i.PrincipalID)) { string tmp = string.Empty; - if (!Util.ParseUniversalUserIdentifier(d.PrincipalID, out i.PrincipalID, out tmp, out tmp, out tmp)) + if (!Util.ParseUniversalUserIdentifier(d.PrincipalID, out i.PrincipalID, out tmp, out tmp, out tmp, out tmp)) // bad record. ignore this entry continue; } @@ -101,6 +101,11 @@ namespace OpenSim.Services.Friends return m_Database.Store(d); } + public bool Delete(string principalID, string friend) + { + return m_Database.Delete(principalID, friend); + } + public virtual bool Delete(UUID PrincipalID, string Friend) { return m_Database.Delete(PrincipalID, Friend); diff --git a/OpenSim/Services/HypergridService/HGFriendsService.cs b/OpenSim/Services/HypergridService/HGFriendsService.cs deleted file mode 100644 index 1829ae3116..0000000000 --- a/OpenSim/Services/HypergridService/HGFriendsService.cs +++ /dev/null @@ -1,86 +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 OpenMetaverse; -using OpenSim.Framework; -using System; -using System.Collections.Generic; -using OpenSim.Services.Interfaces; -using OpenSim.Services.Friends; -using OpenSim.Data; -using Nini.Config; -using log4net; -using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; - -namespace OpenSim.Services.HypergridService -{ - public class HGFriendsService : FriendsService, IFriendsService - { - public HGFriendsService(IConfigSource config) : base(config) - { - } - - /// - /// Overrides base. - /// Storing new friendships from the outside is a tricky, sensitive operation, and it - /// needs to be done under certain restrictions. - /// First of all, if the friendship already exists, this is a no-op. In other words, - /// we cannot change just the flags, it needs to be a new friendship. - /// Second, we store it as flags=0 always, independent of what the caller sends. The - /// owner of the friendship needs to confirm when it gets back home. - /// - /// - /// - /// - /// - public override bool StoreFriend(string PrincipalID, string Friend, int flags) - { - UUID userID; - if (UUID.TryParse(PrincipalID, out userID)) - { - FriendsData[] friendsData = m_Database.GetFriends(userID.ToString()); - List fList = new List(friendsData); - if (fList.Find(delegate(FriendsData fdata) - { - return fdata.Friend == Friend; - }) != null) - return false; - } - else - return false; - - FriendsData d = new FriendsData(); - d.PrincipalID = PrincipalID; - d.Friend = Friend; - d.Data = new Dictionary(); - d.Data["Flags"] = "0"; - - return m_Database.Store(d); - } - - } -} diff --git a/OpenSim/Services/Interfaces/IFriendsService.cs b/OpenSim/Services/Interfaces/IFriendsService.cs index 0a8efad11a..1664f3b3e1 100644 --- a/OpenSim/Services/Interfaces/IFriendsService.cs +++ b/OpenSim/Services/Interfaces/IFriendsService.cs @@ -77,5 +77,6 @@ namespace OpenSim.Services.Interfaces FriendInfo[] GetFriends(string PrincipalID); bool StoreFriend(string PrincipalID, string Friend, int flags); bool Delete(UUID PrincipalID, string Friend); + bool Delete(string PrincipalID, string Friend); } } diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index 4fac951659..f68c078c39 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -628,7 +628,7 @@ namespace OpenSim.Services.LLLoginService else { string tmp; - if (Util.ParseUniversalUserIdentifier(finfo.Friend, out friendID, out tmp, out tmp, out tmp)) + if (Util.ParseUniversalUserIdentifier(finfo.Friend, out friendID, out tmp, out tmp, out tmp, out tmp)) buddyitem.BuddyID = friendID.ToString(); else // junk entry diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index 324c258c30..f8e8ae2062 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -142,7 +142,7 @@ UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" [HGFriendsService] - LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGFriendsService" + LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService" UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" ;; This should always be the very last thing on this file From 24c00acedc1575bf11fb5801bebdc5d45a93c277 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 23 May 2011 02:52:28 +0100 Subject: [PATCH 044/186] Fix Mantis #4429: Allow llGiveInventory to work across sim borders. --- .../Shared/Api/Implementation/LSL_Api.cs | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e3d0dac208..ce7d97ce6c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3864,9 +3864,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); } - // check if destination is an avatar - if (World.GetScenePresence(destId) != null) + // check if destination is an object + if (World.GetSceneObjectPart(destId) != null) { + // destination is an object + World.MoveTaskInventoryItem(destId, m_host, objId); + } + else + { + ScenePresence presence = World.GetScenePresence(destId); + + if (presence == null) + { + UserAccount account = + World.UserAccountService.GetUserAccount( + World.RegionInfo.ScopeID, + destId); + + if (account == null) + { + llSay(0, "Can't find destination "+destId.ToString()); + return; + } + } // destination is an avatar InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); @@ -3887,16 +3907,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AbsolutePosition.ToString(), agentItem.ID, true, m_host.AbsolutePosition, bucket); - if (m_TransferModule != null) m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); + ScriptSleep(3000); } - else - { - // destination is an object - World.MoveTaskInventoryItem(destId, m_host, objId); - } - ScriptSleep(3000); } public void llRemoveInventory(string name) From 178d541dcaa2d8258e3820b39818d8fd69def72e Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 24 May 2011 00:53:28 +0200 Subject: [PATCH 045/186] Add an event for an orderly region shutdown that fires once per region before the SceneGraph is torn down. --- .../Region/Framework/Scenes/EventManager.cs | 25 +++++++++++++++++++ OpenSim/Region/Framework/Scenes/Scene.cs | 2 ++ 2 files changed, 27 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index fd6253533a..e04317b12b 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -111,6 +111,10 @@ namespace OpenSim.Region.Framework.Scenes public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; + public delegate void SceneShuttingDownDelegate(Scene scene); + + public event SceneShuttingDownDelegate OnSceneShuttingDown; + /// /// Fired when an object is touched/grabbed. /// @@ -2193,5 +2197,26 @@ namespace OpenSim.Region.Framework.Scenes } } } + + public void TriggerSceneShuttingDown(Scene s) + { + SceneShuttingDownDelegate handler = OnSceneShuttingDown; + if (handler != null) + { + foreach (SceneShuttingDownDelegate d in handler.GetInvocationList()) + { + try + { + d(s); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[EVENT MANAGER]: Delegate for TriggerSceneShuttingDown failed - continuing. {0} {1}", + e.Message, e.StackTrace); + } + } + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b9690fe70b..eabc9a684e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1064,6 +1064,8 @@ namespace OpenSim.Region.Framework.Scenes shuttingdown = true; m_log.Debug("[SCENE]: Persisting changed objects"); + EventManager.TriggerSceneShuttingDown(this); + EntityBase[] entities = GetEntities(); foreach (EntityBase entity in entities) { From 61d4291da56e18c7777adebbcfce2c092a2d9a69 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 24 May 2011 03:17:12 +0100 Subject: [PATCH 046/186] Create a method to force the script engine to save state from outside --- .../Region/Framework/Interfaces/IScriptModule.cs | 2 ++ OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs index fecdd1b9b8..d9752e64a5 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs @@ -50,5 +50,7 @@ namespace OpenSim.Region.Framework.Interfaces void ResumeScript(UUID itemID); ArrayList GetScriptErrors(UUID itemID); + + void SaveAllState(); } } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 97ab411dd2..d253c6a87d 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -393,11 +393,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine return 0; } - public object DoMaintenance(object p) + public void SaveAllState() { - object[] parms = (object[])p; - int sleepTime = (int)parms[0]; - foreach (IScriptInstance inst in m_Scripts.Values) { if (inst.EventTime() > m_EventLimit) @@ -407,6 +404,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine inst.Start(); } } + } + + public object DoMaintenance(object p) + { + object[] parms = (object[])p; + int sleepTime = (int)parms[0]; + + SaveAllState(); System.Threading.Thread.Sleep(sleepTime); From 24f28d353427d1905ae1a46408841265379e29c3 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 23 May 2011 19:45:39 -0700 Subject: [PATCH 047/186] HG friends: Status notifications working. Also initial logins get the online friends in other grids. --- .../Avatar/Friends/FriendsModule.cs | 94 +++++----- .../Avatar/Friends/HGFriendsModule.cs | 162 ++++++++++++++++- .../HypergridServiceInConnectorModule.cs | 3 +- .../Hypergrid/HGFriendsServerPostHandler.cs | 4 + .../Hypergrid/UserAgentServerConnector.cs | 84 ++++++++- .../Hypergrid/UserAgentServiceConnector.cs | 91 +++++++++ .../HypergridService/UserAgentService.cs | 172 +++++++++++++++++- .../Services/Interfaces/IGatekeeperService.cs | 3 + .../Interfaces/ISimulatorSocialService.cs | 40 ++++ bin/config-include/StandaloneHypergrid.ini | 3 + 10 files changed, 603 insertions(+), 53 deletions(-) create mode 100644 OpenSim/Services/Interfaces/ISimulatorSocialService.cs diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 7d948136f1..f82716d50f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -139,7 +139,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (moduleConfig != null) { string name = moduleConfig.GetString("FriendsModule", "FriendsModule"); - m_log.DebugFormat("[XXX] {0} compared to {1}", name, Name); if (name == Name) { InitModule(config); @@ -183,7 +182,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { } - public void AddRegion(Scene scene) + public virtual void AddRegion(Scene scene) { if (!m_Enabled) return; @@ -302,6 +301,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { UUID agentID = client.AgentId; + //m_log.DebugFormat("[XXX]: OnClientLogin!"); // Inform the friends that this user is online StatusChange(agentID, true); @@ -405,19 +405,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } if (friendList.Count > 0) - { - PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray()); - foreach (PresenceInfo pi in presence) - { - UUID presenceID; - if (UUID.TryParse(pi.UserID, out presenceID)) - online.Add(presenceID); - } - } + GetOnlineFriends(userID, friendList, online); return online; } + protected virtual void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) + { + PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray()); + foreach (PresenceInfo pi in presence) + { + UUID presenceID; + if (UUID.TryParse(pi.UserID, out presenceID)) + online.Add(presenceID); + } + } + /// /// Find the client for a ID /// @@ -472,51 +475,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends Util.FireAndForget( delegate { - foreach (FriendInfo fi in friendList) - { - //m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID); - // Notify about this user status - StatusNotify(fi, agentID, online); - } + m_log.DebugFormat("[FRIENDS MODULE]: Notifying {0} friends", friendList.Count); + // Notify about this user status + StatusNotify(friendList, agentID, online); } ); } } - private void StatusNotify(FriendInfo friend, UUID userID, bool online) + protected virtual void StatusNotify(List friendList, UUID userID, bool online) { - UUID friendID; - if (UUID.TryParse(friend.Friend, out friendID)) + foreach (FriendInfo friend in friendList) { - // Try local - if (LocalStatusNotification(userID, friendID, online)) - return; - - // The friend is not here [as root]. Let's forward. - PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); - if (friendSessions != null && friendSessions.Length > 0) + UUID friendID; + if (UUID.TryParse(friend.Friend, out friendID)) { - PresenceInfo friendSession = null; - foreach (PresenceInfo pinfo in friendSessions) - if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad - { - friendSession = pinfo; - break; - } + // Try local + if (LocalStatusNotification(userID, friendID, online)) + return; - if (friendSession != null) + // The friend is not here [as root]. Let's forward. + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); - m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); - } - } + PresenceInfo friendSession = null; + foreach (PresenceInfo pinfo in friendSessions) + if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad + { + friendSession = pinfo; + break; + } - // Friend is not online. Ignore. - } - else - { - m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); + m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); + } + } + + // Friend is not online. Ignore. + } + else + { + m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); + } } } @@ -670,7 +673,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends FriendInfo[] friends = GetFriends(remoteClient.AgentId); if (friends.Length == 0) { - m_log.DebugFormat("[XXX]: agent {0} has no friends", requester); return; } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index c55839f20b..b0a75674e6 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -46,7 +46,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Region.CoreModules.Avatar.Friends { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule + public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -56,6 +56,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends get { return "HGFriendsModule"; } } + public override void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + base.AddRegion(scene); + scene.RegisterModuleInterface(this); + } + + #endregion + + #region IFriendsSimConnector + + /// + /// Notify the user that the friend's status changed + /// + /// user to be notified + /// friend whose status changed + /// status + /// + public bool StatusNotify(UUID userID, UUID friendID, bool online) + { + return LocalStatusNotification(friendID, userID, online); + } + #endregion protected override bool FetchFriendslist(IClientAPI client) @@ -103,6 +128,140 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return false; } + protected override void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) + { + // Let's single out the UUIs + List localFriends = new List(); + List foreignFriends = new List(); + string tmp = string.Empty; + + foreach (string s in friendList) + { + UUID id; + if (UUID.TryParse(s, out id)) + localFriends.Add(s); + else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp)) + { + foreignFriends.Add(s); + // add it here too, who knows maybe the foreign friends happens to be on this grid + localFriends.Add(id.ToString()); + } + } + + // OK, see who's present on this grid + List toBeRemoved = new List(); + PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray()); + foreach (PresenceInfo pi in presence) + { + UUID presenceID; + if (UUID.TryParse(pi.UserID, out presenceID)) + { + online.Add(presenceID); + foreach (string s in foreignFriends) + if (s.StartsWith(pi.UserID)) + toBeRemoved.Add(s); + } + } + + foreach (string s in toBeRemoved) + foreignFriends.Remove(s); + + // OK, let's send this up the stack, and leave a closure here + // collecting online friends in other grids + Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); }); + + } + + private void CollectOnlineFriendsElsewhere(UUID userID, List foreignFriends) + { + // let's divide the friends on a per-domain basis + Dictionary> friendsPerDomain = new Dictionary>(); + foreach (string friend in foreignFriends) + { + UUID friendID; + if (!UUID.TryParse(friend, out friendID)) + { + // it's a foreign friend + string url = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp)) + { + if (!friendsPerDomain.ContainsKey(url)) + friendsPerDomain[url] = new List(); + friendsPerDomain[url].Add(friend); + } + } + } + + // Now, call those worlds + + foreach (KeyValuePair> kvp in friendsPerDomain) + { + List ids = new List(); + foreach (string f in kvp.Value) + ids.Add(f); + UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + List online = uConn.GetOnlineFriends(userID, ids); + // Finally send the notifications to the user + // this whole process may take a while, so let's check at every + // iteration that the user is still here + IClientAPI client = LocateClientObject(userID); + if (client != null) + client.SendAgentOnline(online.ToArray()); + else + break; + } + + } + + protected override void StatusNotify(List friendList, UUID userID, bool online) + { + // First, let's divide the friends on a per-domain basis + Dictionary> friendsPerDomain = new Dictionary>(); + foreach (FriendInfo friend in friendList) + { + UUID friendID; + if (UUID.TryParse(friend.Friend, out friendID)) + { + if (!friendsPerDomain.ContainsKey("local")) + friendsPerDomain["local"] = new List(); + friendsPerDomain["local"].Add(friend); + } + else + { + // it's a foreign friend + string url = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out tmp, out tmp, out tmp)) + { + // Let's try our luck in the local sim. Who knows, maybe it's here + if (LocalStatusNotification(userID, friendID, online)) + continue; + + if (!friendsPerDomain.ContainsKey(url)) + friendsPerDomain[url] = new List(); + friendsPerDomain[url].Add(friend); + } + } + } + + // For the local friends, just call the base method + // Let's do this first of all + if (friendsPerDomain.ContainsKey("local")) + base.StatusNotify(friendsPerDomain["local"], userID, online); + + foreach (KeyValuePair> kvp in friendsPerDomain) + { + if (kvp.Key != "local") + { + // For the others, call the user agent service + List ids = new List(); + foreach (FriendInfo f in kvp.Value) + ids.Add(f.Friend); + UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + uConn.StatusNotification(ids, userID, online); + } + } + } + protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) { first = "Unknown"; last = "User"; @@ -172,7 +331,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); - m_log.DebugFormat("[XXX] GetFriendsFromService to {0}", agentUUI); finfos = FriendsService.GetFriends(agentUUI); m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI); } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs index f5b6817638..a5b5637961 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs @@ -113,7 +113,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid ISimulationService simService = scene.RequestModuleInterface(); m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService); - new UserAgentServerConnector(m_Config, MainServer.Instance); + IFriendsSimConnector friendsConn = scene.RequestModuleInterface(); + new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn); new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService"); new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService"); } diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs index a83d0e8b44..841811e843 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs @@ -140,16 +140,20 @@ namespace OpenSim.Server.Handlers.Hypergrid byte[] NewFriendship(Dictionary request) { + m_log.DebugFormat("[XXX] 1"); if (!VerifyServiceKey(request)) return FailureResult(); + m_log.DebugFormat("[XXX] 2"); // OK, can proceed FriendInfo friend = new FriendInfo(request); UUID friendID; string tmp = string.Empty; + m_log.DebugFormat("[XXX] 3"); if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp)) return FailureResult(); + m_log.DebugFormat("[HGFRIENDS HANDLER]: New friendship {0} {1}", friend.PrincipalID, friend.Friend); // If the friendship already exists, return fail diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index 0e8ce800a7..7a9fb4bcf1 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -54,13 +54,19 @@ namespace OpenSim.Server.Handlers.Hypergrid private IUserAgentService m_HomeUsersService; public UserAgentServerConnector(IConfigSource config, IHttpServer server) : + this(config, server, null) + { + } + + public UserAgentServerConnector(IConfigSource config, IHttpServer server, IFriendsSimConnector friendsConnector) : base(config, server, String.Empty) { IConfig gridConfig = config.Configs["UserAgentService"]; if (gridConfig != null) { string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty); - Object[] args = new Object[] { config }; + + Object[] args = new Object[] { config, friendsConnector }; m_HomeUsersService = ServerUtils.LoadPlugin(serviceDll, args); } if (m_HomeUsersService == null) @@ -75,6 +81,9 @@ namespace OpenSim.Server.Handlers.Hypergrid server.AddXmlRPCHandler("verify_client", VerifyClient, false); server.AddXmlRPCHandler("logout_agent", LogoutAgent, false); + server.AddXmlRPCHandler("status_notification", StatusNotification, false); + server.AddXmlRPCHandler("get_online_friends", GetOnlineFriends, false); + server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); } @@ -194,5 +203,78 @@ namespace OpenSim.Server.Handlers.Hypergrid } + public XmlRpcResponse StatusNotification(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + hash["result"] = "false"; + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID") && requestData.ContainsKey("online")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + List ids = new List(); + foreach (object key in requestData.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null) + ids.Add(requestData[key].ToString()); + } + bool online = false; + bool.TryParse(requestData["online"].ToString(), out online); + + hash["result"] = "true"; + + // let's spawn a thread for this, because it may take a long time... + Util.FireAndForget(delegate { m_HomeUsersService.StatusNotification(ids, userID, online); }); + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + + public XmlRpcResponse GetOnlineFriends(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + List ids = new List(); + foreach (object key in requestData.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null) + ids.Add(requestData[key].ToString()); + } + + // let's spawn a thread for this, because it may take a long time... + List online = m_HomeUsersService.GetOnlineFriends(userID, ids); + if (online.Count > 0) + { + int i = 0; + foreach (UUID id in online) + { + hash["friend_" + i.ToString()] = id.ToString(); + i++; + } + + } + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + } } diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index c40a3474a3..46d30df1dc 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -404,6 +404,97 @@ namespace OpenSim.Services.Connectors.Hypergrid GetBoolResponse(request, out reason); } + public void StatusNotification(List friends, UUID userID, bool online) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + hash["online"] = online.ToString(); + int i = 0; + foreach (string s in friends) + { + hash["friend_" + i.ToString()] = s; + i++; + } + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("status_notification", paramList); + string reason = string.Empty; + GetBoolResponse(request, out reason); + + } + + public List GetOnlineFriends(UUID userID, List friends) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + int i = 0; + foreach (string s in friends) + { + hash["friend_" + i.ToString()] = s; + i++; + } + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("get_online_friends", paramList); + string reason = string.Empty; + + // Send and get reply + List online = new List(); + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return online; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return online; + } + + 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]: Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return online; + } + + // Here is the actual response + foreach (object key in hash.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null) + { + UUID uuid; + if (UUID.TryParse(hash[key].ToString(), out uuid)) + online.Add(uuid); + } + } + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); + reason = "Exception: " + e.Message; + } + + return online; + } private bool GetBoolResponse(XmlRpcRequest request, out string reason) { diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 445d45e250..01815335aa 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -31,10 +31,12 @@ using System.Net; using System.Reflection; using OpenSim.Framework; +using OpenSim.Services.Connectors.Friends; using OpenSim.Services.Connectors.Hypergrid; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Server.Base; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; using OpenMetaverse; using log4net; @@ -63,19 +65,34 @@ namespace OpenSim.Services.HypergridService protected static IGridService m_GridService; protected static GatekeeperServiceConnector m_GatekeeperConnector; protected static IGatekeeperService m_GatekeeperService; + protected static IFriendsService m_FriendsService; + protected static IPresenceService m_PresenceService; + protected static IFriendsSimConnector m_FriendsLocalSimConnector; // standalone, points to HGFriendsModule + protected static FriendsSimConnector m_FriendsSimConnector; // grid protected static string m_GridName; protected static bool m_BypassClientVerification; - public UserAgentService(IConfigSource config) + public UserAgentService(IConfigSource config) : this(config, null) { + } + + public UserAgentService(IConfigSource config, IFriendsSimConnector friendsConnector) + { + // Let's set this always, because we don't know the sequence + // of instantiations + if (friendsConnector != null) + m_FriendsLocalSimConnector = friendsConnector; + if (!m_Initialized) { m_Initialized = true; m_log.DebugFormat("[HOME USERS SECURITY]: Starting..."); - + + m_FriendsSimConnector = new FriendsSimConnector(); + IConfig serverConfig = config.Configs["UserAgentService"]; if (serverConfig == null) throw new Exception(String.Format("No section UserAgentService in config file")); @@ -83,6 +100,8 @@ namespace OpenSim.Services.HypergridService string gridService = serverConfig.GetString("GridService", String.Empty); string gridUserService = serverConfig.GetString("GridUserService", String.Empty); string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty); + string friendsService = serverConfig.GetString("FriendsService", String.Empty); + string presenceService = serverConfig.GetString("PresenceService", String.Empty); m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false); @@ -94,6 +113,8 @@ namespace OpenSim.Services.HypergridService m_GridUserService = ServerUtils.LoadPlugin(gridUserService, args); m_GatekeeperConnector = new GatekeeperServiceConnector(); m_GatekeeperService = ServerUtils.LoadPlugin(gatekeeperService, args); + m_FriendsService = ServerUtils.LoadPlugin(friendsService, args); + m_PresenceService = ServerUtils.LoadPlugin(presenceService, args); m_GridName = serverConfig.GetString("ExternalName", string.Empty); if (m_GridName == string.Empty) @@ -156,11 +177,16 @@ namespace OpenSim.Services.HypergridService string gridName = gatekeeper.ServerURI; m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); - + if (m_GridName == gridName) success = m_GatekeeperService.LoginAgent(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); + } if (!success) { @@ -179,6 +205,7 @@ namespace OpenSim.Services.HypergridService if (clientIP != null) m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; + return true; } @@ -291,6 +318,145 @@ namespace OpenSim.Services.HypergridService return false; } + public void StatusNotification(List friends, UUID foreignUserID, bool online) + { + if (m_FriendsService == null || m_PresenceService == null) + { + m_log.WarnFormat("[USER AGENT SERVICE]: Unable to perform status notifications because friends or presence services are missing"); + return; + } + + m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: foreign user {0} wants to notify {1} local friends", foreignUserID, friends.Count); + + // First, let's double check that the reported friends are, indeed, friends of that user + // And let's check that the secret matches + List usersToBeNotified = new List(); + foreach (string uui in friends) + { + UUID localUserID; + string secret = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret)) + { + FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID); + foreach (FriendInfo finfo in friendInfos) + { + if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret)) + { + // great! + usersToBeNotified.Add(localUserID.ToString()); + } + } + } + } + + // Now, let's send the notifications + m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: user has {0} local friends", usersToBeNotified.Count); + + // First, let's send notifications to local users who are online in the home grid + PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray()); + if (friendSessions != null && friendSessions.Length > 0) + { + PresenceInfo friendSession = null; + foreach (PresenceInfo pinfo in friendSessions) + if (pinfo.RegionID != UUID.Zero) // let's guard against traveling agents + { + friendSession = pinfo; + break; + } + + if (friendSession != null) + { + ForwardStatusNotificationToSim(friendSession.RegionID, friendSession.UserID, foreignUserID, online); + usersToBeNotified.Remove(friendSession.UserID.ToString()); + } + } + + // 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); + } + } + } + + protected void ForwardStatusNotificationToSim(UUID regionID, string user, UUID foreignUserID, bool online) + { + UUID userID; + if (UUID.TryParse(user, out userID)) + { + if (m_FriendsLocalSimConnector != null) + { + m_log.DebugFormat("[USER AGENT SERVICE]: Local Notify, user {0} is {1}", foreignUserID, (online ? "online" : "offline")); + m_FriendsLocalSimConnector.StatusNotify(userID, foreignUserID, online); + } + else + { + GridRegion region = m_GridService.GetRegionByUUID(UUID.Zero /* !!! */, regionID); + if (region != null) + { + m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, user, foreignUserID, (online ? "online" : "offline")); + m_FriendsSimConnector.StatusNotify(region, userID, foreignUserID, online); + } + } + } + } + + public List GetOnlineFriends(UUID foreignUserID, List friends) + { + List online = new List(); + + if (m_FriendsService == null || m_PresenceService == null) + { + m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get online friends because friends or presence services are missing"); + return online; + } + + m_log.DebugFormat("[USER AGENT SERVICE]: Foreign user {0} wants to know status of {1} local friends", foreignUserID, friends.Count); + + // First, let's double check that the reported friends are, indeed, friends of that user + // And let's check that the secret matches and the rights + List usersToBeNotified = new List(); + foreach (string uui in friends) + { + UUID localUserID; + string secret = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret)) + { + FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID); + foreach (FriendInfo finfo in friendInfos) + { + if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret) && + (finfo.TheirFlags & (int)FriendRights.CanSeeOnline) != 0 && (finfo.TheirFlags != -1)) + { + // great! + usersToBeNotified.Add(localUserID.ToString()); + } + } + } + } + + // Now, let's find out their status + m_log.DebugFormat("[USER AGENT SERVICE]: GetOnlineFriends: user has {0} local friends with status rights", usersToBeNotified.Count); + + // First, let's send notifications to local users who are online in the home grid + PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray()); + if (friendSessions != null && friendSessions.Length > 0) + { + foreach (PresenceInfo pi in friendSessions) + { + UUID presenceID; + if (UUID.TryParse(pi.UserID, out presenceID)) + online.Add(presenceID); + } + } + + return online; + } } class TravelingAgentInfo diff --git a/OpenSim/Services/Interfaces/IGatekeeperService.cs b/OpenSim/Services/Interfaces/IGatekeeperService.cs index aac82936b0..fa1ab1c7bb 100644 --- a/OpenSim/Services/Interfaces/IGatekeeperService.cs +++ b/OpenSim/Services/Interfaces/IGatekeeperService.cs @@ -55,6 +55,9 @@ namespace OpenSim.Services.Interfaces void LogoutAgent(UUID userID, UUID sessionID); GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); + void StatusNotification(List friends, UUID userID, bool online); + List GetOnlineFriends(UUID userID, List friends); + bool AgentIsComingHome(UUID sessionID, string thisGridExternalName); bool VerifyAgent(UUID sessionID, string token); bool VerifyClient(UUID sessionID, string reportedIP); diff --git a/OpenSim/Services/Interfaces/ISimulatorSocialService.cs b/OpenSim/Services/Interfaces/ISimulatorSocialService.cs new file mode 100644 index 0000000000..0b7aefcf35 --- /dev/null +++ b/OpenSim/Services/Interfaces/ISimulatorSocialService.cs @@ -0,0 +1,40 @@ +/* + * 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 GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Services.Interfaces +{ + public interface IFriendsSimConnector + { + bool StatusNotify(UUID userID, UUID friendID, bool online); + } +} diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index f8e8ae2062..f56bccd0c2 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -126,6 +126,9 @@ GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" GridService = "OpenSim.Services.GridService.dll:GridService" GatekeeperService = "OpenSim.Services.HypergridService.dll:GatekeeperService" + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" + ;; The interface that local users get when they are in other grids From 28c25d8477ff3cfd5751da1454fcd4cc33815a5e Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 24 May 2011 03:37:25 +0200 Subject: [PATCH 048/186] Allow disabling the legacy backup mechanism to avoid the object clone if backup is not used. --- OpenSim/Region/Framework/Scenes/Scene.cs | 9 +++++++++ OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index eabc9a684e..4aae13c0ee 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -204,6 +204,7 @@ namespace OpenSim.Region.Framework.Scenes private Timer m_mapGenerationTimer = new Timer(); private bool m_generateMaptiles; + private bool m_useBackup = true; // private Dictionary m_UserNamesCache = new Dictionary(); @@ -459,6 +460,11 @@ namespace OpenSim.Region.Framework.Scenes get { return m_sceneGraph; } } + public bool UseBackup + { + get { return m_useBackup; } + } + // an instance to the physics plugin's Scene object. public PhysicsScene PhysicsScene { @@ -647,6 +653,9 @@ namespace OpenSim.Region.Framework.Scenes IConfig startupConfig = m_config.Configs["Startup"]; m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); + m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup); + if (!m_useBackup) + m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); //Animation states m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 19a95062b4..9b9374b329 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1335,7 +1335,7 @@ namespace OpenSim.Region.Framework.Scenes } } - if (HasGroupChanged) + if (m_scene.UseBackup && HasGroupChanged) { // don't backup while it's selected or you're asking for changes mid stream. if (isTimeToPersist() || forcedBackup) From e19031849ec2957f7312d7e2417bd8c8da0efc53 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 24 May 2011 09:38:03 -0700 Subject: [PATCH 049/186] Added necessary code to drop inventory on hg friends using the profile window, but can't test because this mechanism doesn't seem to work without a profile service. --- .../HGInventoryAccessModule.cs | 14 ++-- .../UserManagement/UserManagementModule.cs | 36 +++++++++- .../Inventory/HGInventoryBroker.cs | 16 +++++ .../Framework/Interfaces/IUserManagement.cs | 2 + .../Hypergrid/UserAgentServerConnector.cs | 34 +++++++++- .../Hypergrid/UserAgentServiceConnector.cs | 66 ++++++++++++++++++- .../HypergridService/UserAgentService.cs | 17 +++++ .../Services/Interfaces/IGatekeeperService.cs | 1 + .../Services/LLLoginService/LLLoginService.cs | 30 ++++++--- bin/config-include/StandaloneHypergrid.ini | 2 +- 10 files changed, 197 insertions(+), 21 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 52791cb046..429dda7313 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -110,7 +110,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel) { string userAssetServer = string.Empty; - if (IsForeignUser(avatarID, out userAssetServer) && m_OutboundPermission) + if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) { Util.FireAndForget(delegate { m_assMapper.Post(assetID, avatarID, userAssetServer); }); } @@ -180,10 +180,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver) { string userAssetServer = string.Empty; - if (IsForeignUser(sender, out userAssetServer)) + if (IsForeignUser(sender, out userAssetServer) && userAssetServer != string.Empty) m_assMapper.Get(item.AssetID, sender, userAssetServer); - if (IsForeignUser(receiver, out userAssetServer) && m_OutboundPermission) + if (IsForeignUser(receiver, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) m_assMapper.Post(item.AssetID, receiver, userAssetServer); } @@ -203,9 +203,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) { assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString(); - assetServerURL = assetServerURL.Trim(new char[] { '/' }); return true; + assetServerURL = assetServerURL.Trim(new char[] { '/' }); } } + else + { + assetServerURL = UserManagementModule.GetUserServerURL(userID, "AssetServerURI"); + assetServerURL = assetServerURL.Trim(new char[] { '/' }); + } + return true; } return false; diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 795de098b2..4d073b2fe0 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -35,6 +35,7 @@ using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.Hypergrid; using OpenMetaverse; using log4net; @@ -47,7 +48,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public UUID Id; public string FirstName; public string LastName; - public string ProfileURL; + public string HomeURL; + public Dictionary ServerURLs; } public class UserManagementModule : ISharedRegionModule, IUserManagement @@ -224,6 +226,34 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement return "(hippos)"; } + public string GetUserHomeURL(UUID userID) + { + if (m_UserCache.ContainsKey(userID)) + return m_UserCache[userID].HomeURL; + + return string.Empty; + } + + public string GetUserServerURL(UUID userID, string serverType) + { + if (m_UserCache.ContainsKey(userID)) + { + UserData userdata = m_UserCache[userID]; + if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) + return userdata.ServerURLs[serverType].ToString(); + + if (userdata.HomeURL != string.Empty) + { + UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL); + userdata.ServerURLs = uConn.GetServerURLs(userID); + if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) + return userdata.ServerURLs[serverType].ToString(); + } + } + + return string.Empty; + } + public void AddUser(UUID id, string creatorData) { if (m_UserCache.ContainsKey(id)) @@ -249,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement string[] parts = creatorData.Split(';'); if (parts.Length >= 1) { - user.ProfileURL = parts[0]; + user.HomeURL = parts[0]; try { Uri uri = new Uri(parts[0]); @@ -274,7 +304,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement lock (m_UserCache) m_UserCache[id] = user; - m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.ProfileURL); + m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.HomeURL); } public void AddUser(UUID uuid, string first, string last, string profileURL) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index 3f63db371f..eef60a10da 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -58,6 +58,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory private List m_Scenes = new List(); + protected IUserManagement m_UserManagement; + protected IUserManagement UserManagementModule + { + get + { + if (m_UserManagement == null) + m_UserManagement = m_Scenes[0].RequestModuleInterface(); + return m_UserManagement; + } + } + public Type ReplaceableInterface { get { return null; } @@ -206,6 +217,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return; } } + else + { + inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI"); + inventoryURL = inventoryURL.Trim(new char[] { '/' }); + } } } } diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs index 2904ee87dc..9cac3b061a 100644 --- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs +++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs @@ -8,6 +8,8 @@ namespace OpenSim.Region.Framework.Interfaces public interface IUserManagement { string GetUserName(UUID uuid); + string GetUserHomeURL(UUID uuid); + string GetUserServerURL(UUID uuid, string serverType); void AddUser(UUID uuid, string userData); void AddUser(UUID uuid, string firstName, string lastName, string profileURL); } diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index 7a9fb4bcf1..e51fe0bc26 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -83,6 +83,7 @@ namespace OpenSim.Server.Handlers.Hypergrid server.AddXmlRPCHandler("status_notification", StatusNotification, false); server.AddXmlRPCHandler("get_online_friends", GetOnlineFriends, false); + server.AddXmlRPCHandler("get_server_urls", GetServerURLs, false); server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); } @@ -256,7 +257,6 @@ namespace OpenSim.Server.Handlers.Hypergrid ids.Add(requestData[key].ToString()); } - // let's spawn a thread for this, because it may take a long time... List online = m_HomeUsersService.GetOnlineFriends(userID, ids); if (online.Count > 0) { @@ -266,8 +266,38 @@ namespace OpenSim.Server.Handlers.Hypergrid hash["friend_" + i.ToString()] = id.ToString(); i++; } - } + else + hash["result"] = "No Friends Online"; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + + public XmlRpcResponse GetServerURLs(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + Dictionary serverURLs = m_HomeUsersService.GetServerURLs(userID); + if (serverURLs.Count > 0) + { + foreach (KeyValuePair kvp in serverURLs) + hash["SRV_" + kvp.Key] = kvp.Value.ToString(); + } + else + hash["result"] = "No Service URLs"; } XmlRpcResponse response = new XmlRpcResponse(); diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 46d30df1dc..265bacf33e 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -470,7 +470,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]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL); reason = "Internal error 1"; return online; } @@ -496,6 +496,70 @@ namespace OpenSim.Services.Connectors.Hypergrid return online; } + public Dictionary GetServerURLs(UUID userID) + { + 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 (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return serverURLs; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} 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 + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetServerURLs Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return serverURLs; + } + + // 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 (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); + reason = "Exception: " + e.Message; + } + + return serverURLs; + } + private bool GetBoolResponse(XmlRpcRequest request, out string reason) { //m_log.Debug("[USER AGENT CONNECTOR]: GetBoolResponse from/to " + m_ServerURL); diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 01815335aa..e63f941cc3 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -67,6 +67,7 @@ namespace OpenSim.Services.HypergridService protected static IGatekeeperService m_GatekeeperService; protected static IFriendsService m_FriendsService; protected static IPresenceService m_PresenceService; + protected static IUserAccountService m_UserAccountService; protected static IFriendsSimConnector m_FriendsLocalSimConnector; // standalone, points to HGFriendsModule protected static FriendsSimConnector m_FriendsSimConnector; // grid @@ -102,6 +103,7 @@ namespace OpenSim.Services.HypergridService string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty); string friendsService = serverConfig.GetString("FriendsService", String.Empty); string presenceService = serverConfig.GetString("PresenceService", String.Empty); + string userAccountService = serverConfig.GetString("UserAccountService", String.Empty); m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false); @@ -115,6 +117,7 @@ namespace OpenSim.Services.HypergridService m_GatekeeperService = ServerUtils.LoadPlugin(gatekeeperService, args); m_FriendsService = ServerUtils.LoadPlugin(friendsService, args); m_PresenceService = ServerUtils.LoadPlugin(presenceService, args); + m_UserAccountService = ServerUtils.LoadPlugin(userAccountService, args); m_GridName = serverConfig.GetString("ExternalName", string.Empty); if (m_GridName == string.Empty) @@ -457,6 +460,20 @@ namespace OpenSim.Services.HypergridService return online; } + + public Dictionary GetServerURLs(UUID userID) + { + if (m_UserAccountService == null) + { + m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get server URLs because user account service is missing"); + return new Dictionary(); + } + UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero /*!!!*/, userID); + if (account != null) + return account.ServiceURLs; + + return new Dictionary(); + } } class TravelingAgentInfo diff --git a/OpenSim/Services/Interfaces/IGatekeeperService.cs b/OpenSim/Services/Interfaces/IGatekeeperService.cs index fa1ab1c7bb..f1860cce58 100644 --- a/OpenSim/Services/Interfaces/IGatekeeperService.cs +++ b/OpenSim/Services/Interfaces/IGatekeeperService.cs @@ -54,6 +54,7 @@ namespace OpenSim.Services.Interfaces bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason); void LogoutAgent(UUID userID, UUID sessionID); GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); + Dictionary GetServerURLs(UUID userID); void StatusNotification(List friends, UUID userID, bool online); List GetOnlineFriends(UUID userID, List friends); diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 2ca2d1566c..a5a728be78 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -804,16 +804,13 @@ namespace OpenSim.Services.LLLoginService // Old style: get the service keys from the DB foreach (KeyValuePair kvp in account.ServiceURLs) { - if (kvp.Value == null || (kvp.Value != null && kvp.Value.ToString() == string.Empty)) - { - aCircuit.ServiceURLs[kvp.Key] = m_LoginServerConfig.GetString(kvp.Key, string.Empty); - } - else + if (kvp.Value != null) { aCircuit.ServiceURLs[kvp.Key] = kvp.Value; + + if (!aCircuit.ServiceURLs[kvp.Key].ToString().EndsWith("/")) + aCircuit.ServiceURLs[kvp.Key] = aCircuit.ServiceURLs[kvp.Key] + "/"; } - if (!aCircuit.ServiceURLs[kvp.Key].ToString().EndsWith("/")) - aCircuit.ServiceURLs[kvp.Key] = aCircuit.ServiceURLs[kvp.Key] + "/"; } // New style: service keys start with SRV_; override the previous @@ -821,16 +818,29 @@ namespace OpenSim.Services.LLLoginService if (keys.Length > 0) { + bool newUrls = false; IEnumerable serviceKeys = keys.Where(value => value.StartsWith("SRV_")); foreach (string serviceKey in serviceKeys) { string keyName = serviceKey.Replace("SRV_", ""); - aCircuit.ServiceURLs[keyName] = m_LoginServerConfig.GetString(serviceKey, string.Empty); - if (!aCircuit.ServiceURLs[keyName].ToString().EndsWith("/")) - aCircuit.ServiceURLs[keyName] = aCircuit.ServiceURLs[keyName] + "/"; + string keyValue = m_LoginServerConfig.GetString(serviceKey, string.Empty); + if (!keyValue.EndsWith("/")) + keyValue = keyValue + "/"; + + if (!account.ServiceURLs.ContainsKey(keyName) || (account.ServiceURLs.ContainsKey(keyName) && account.ServiceURLs[keyName] != keyValue)) + { + account.ServiceURLs[keyName] = keyValue; + newUrls = true; + } + aCircuit.ServiceURLs[keyName] = keyValue; m_log.DebugFormat("[LLLOGIN SERVICE]: found new key {0} {1}", keyName, aCircuit.ServiceURLs[keyName]); } + + // The grid operator decided to override the defaults in the + // [LoginService] configuration. Let's store the correct ones. + if (newUrls) + m_UserAccountService.StoreUserAccount(account); } } diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index f56bccd0c2..6cd24b09fc 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -128,7 +128,7 @@ GatekeeperService = "OpenSim.Services.HypergridService.dll:GatekeeperService" PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" - + UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService" ;; The interface that local users get when they are in other grids From a8913141c081202eb1f988901a4ac0988bbd72a2 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Tue, 24 May 2011 16:03:01 -0400 Subject: [PATCH 050/186] Make client event handlers for money only work on root agents --- .../World/MoneyModule/SampleMoneyModule.cs | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs index b84a34d288..952e797ada 100644 --- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs +++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs @@ -177,9 +177,37 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule scene.EventManager.OnClientClosed += ClientLoggedOut; scene.EventManager.OnValidateLandBuy += ValidateLandBuy; scene.EventManager.OnLandBuy += processLandBuy; + scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; } } + void OnMakeRootAgent(ScenePresence presence) + { + // Do this only for root agents + // Some implementations register $$ for + // child agents, then that never goes away + // We will send a zero balance when they are + // made root. + // + // Modules overriding this should only deal with + // root agents as well. + // + IClientAPI client = presence.ControllingClient; + + client.OnEconomyDataRequest += EconomyDataRequestHandler; + client.OnMoneyBalanceRequest += SendMoneyBalance; + client.OnRequestPayPrice += requestPayPrice; + client.OnObjectBuy += ObjectBuy; + client.OnLogout += ClientClosed; + + client.SendMoneyBalance (UUID.Random(), true, new byte[0], 0); + } + + void HandleSceneEventManagerOnMakeRootAgent (ScenePresence presence) + { + + } + public void RemoveRegion(Scene scene) { } @@ -277,13 +305,9 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule private void OnNewClient(IClientAPI client) { GetClientFunds(client); + // Moved the event registrations to fire them when + // the agent becomes root - // Subscribe to Money messages - client.OnEconomyDataRequest += EconomyDataRequestHandler; - client.OnMoneyBalanceRequest += SendMoneyBalance; - client.OnRequestPayPrice += requestPayPrice; - client.OnObjectBuy += ObjectBuy; - client.OnLogout += ClientClosed; } /// From ef3f6b4e63a49430bebbc929cb61d018a0a0d37c Mon Sep 17 00:00:00 2001 From: BlueWall Date: Tue, 24 May 2011 16:33:51 -0400 Subject: [PATCH 051/186] Revert "Make client event handlers for money only work on root agents" This reverts commit a8913141c081202eb1f988901a4ac0988bbd72a2. Pulling this back until some testing under various money modules can be done. Need to be able to make purchases as a child agent. --- .../World/MoneyModule/SampleMoneyModule.cs | 36 ++++--------------- 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs index 952e797ada..b84a34d288 100644 --- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs +++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs @@ -177,37 +177,9 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule scene.EventManager.OnClientClosed += ClientLoggedOut; scene.EventManager.OnValidateLandBuy += ValidateLandBuy; scene.EventManager.OnLandBuy += processLandBuy; - scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; } } - void OnMakeRootAgent(ScenePresence presence) - { - // Do this only for root agents - // Some implementations register $$ for - // child agents, then that never goes away - // We will send a zero balance when they are - // made root. - // - // Modules overriding this should only deal with - // root agents as well. - // - IClientAPI client = presence.ControllingClient; - - client.OnEconomyDataRequest += EconomyDataRequestHandler; - client.OnMoneyBalanceRequest += SendMoneyBalance; - client.OnRequestPayPrice += requestPayPrice; - client.OnObjectBuy += ObjectBuy; - client.OnLogout += ClientClosed; - - client.SendMoneyBalance (UUID.Random(), true, new byte[0], 0); - } - - void HandleSceneEventManagerOnMakeRootAgent (ScenePresence presence) - { - - } - public void RemoveRegion(Scene scene) { } @@ -305,9 +277,13 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule private void OnNewClient(IClientAPI client) { GetClientFunds(client); - // Moved the event registrations to fire them when - // the agent becomes root + // Subscribe to Money messages + client.OnEconomyDataRequest += EconomyDataRequestHandler; + client.OnMoneyBalanceRequest += SendMoneyBalance; + client.OnRequestPayPrice += requestPayPrice; + client.OnObjectBuy += ObjectBuy; + client.OnLogout += ClientClosed; } /// From e398c33648dabca1b7243214e3faa1e36f8cf024 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 25 May 2011 12:17:46 +0100 Subject: [PATCH 052/186] Add PayPrice to serialization format Xml2 --- .../Framework/Scenes/SceneObjectPart.cs | 9 ++--- .../Serialization/SceneObjectSerializer.cs | 37 ++++++++++++++++++- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 8a8a6993cc..331abb27b4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -144,11 +144,10 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 StatusSandboxPos; - // TODO: This needs to be persisted in next XML version update! - - public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; - - + [XmlIgnore] + public int[] PayPrice = {-2,-2,-2,-2,-2}; + + [XmlIgnore] public PhysicsActor PhysActor { get { return m_physActor; } diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index bb8a83a1af..872816c450 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -341,6 +341,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl); m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); + m_SOPXmlProcessors.Add("PayPrice0", ProcessPayPrice0); + m_SOPXmlProcessors.Add("PayPrice1", ProcessPayPrice1); + m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); + m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); + m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); #endregion #region TaskInventoryXmlProcessors initialization @@ -698,6 +703,32 @@ namespace OpenSim.Region.Framework.Scenes.Serialization { obj.ParticleSystem = Convert.FromBase64String(reader.ReadElementContentAsString("ParticleSystem", String.Empty)); } + + private static void ProcessPayPrice0(SceneObjectPart obj, XmlTextReader reader) + { + obj.PayPrice[0] = (int)reader.ReadElementContentAsInt("PayPrice0", String.Empty); + } + + private static void ProcessPayPrice1(SceneObjectPart obj, XmlTextReader reader) + { + obj.PayPrice[1] = (int)reader.ReadElementContentAsInt("PayPrice1", String.Empty); + } + + private static void ProcessPayPrice2(SceneObjectPart obj, XmlTextReader reader) + { + obj.PayPrice[2] = (int)reader.ReadElementContentAsInt("PayPrice2", String.Empty); + } + + private static void ProcessPayPrice3(SceneObjectPart obj, XmlTextReader reader) + { + obj.PayPrice[3] = (int)reader.ReadElementContentAsInt("PayPrice3", String.Empty); + } + + private static void ProcessPayPrice4(SceneObjectPart obj, XmlTextReader reader) + { + obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); + } + #endregion #region TaskInventoryXmlProcessors @@ -1069,7 +1100,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization shp.Media = PrimitiveBaseShape.MediaList.FromXml(value); } - #endregion ////////// Write ///////// @@ -1175,6 +1205,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); WriteBytes(writer, "TextureAnimation", sop.TextureAnimation); WriteBytes(writer, "ParticleSystem", sop.ParticleSystem); + writer.WriteElementString("PayPrice0", sop.PayPrice[0].ToString()); + writer.WriteElementString("PayPrice1", sop.PayPrice[1].ToString()); + writer.WriteElementString("PayPrice2", sop.PayPrice[2].ToString()); + writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); + writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); writer.WriteEndElement(); } From 5c2168cae758ae19367f4c2f5a02713e74fc0912 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 25 May 2011 12:32:21 -0700 Subject: [PATCH 053/186] HG: Instant Message working. Tested on HG standalones only. Needs a lot more testing. --- .../InstantMessage/HGMessageTransferModule.cs | 268 +++++++++++++++ .../InstantMessageServerConnector.cs | 280 ++++++++++++++++ .../Hypergrid/UserAgentServerConnector.cs | 48 +++ .../Hypergrid/UserAgentServiceConnector.cs | 58 ++++ .../InstantMessageServiceConnector.cs | 129 ++++++++ .../HGInstantMessageService.cs | 311 ++++++++++++++++++ .../HypergridService/UserAgentService.cs | 11 + .../Services/Interfaces/IGatekeeperService.cs | 8 + .../Interfaces/ISimulatorSocialService.cs | 5 + bin/config-include/StandaloneHypergrid.ini | 10 + 10 files changed, 1128 insertions(+) create mode 100644 OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs create mode 100644 OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs create mode 100644 OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs create mode 100644 OpenSim/Services/HypergridService/HGInstantMessageService.cs diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs new file mode 100644 index 0000000000..9ba4e4953d --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs @@ -0,0 +1,268 @@ +/* + * 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.Reflection; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using Mono.Addins; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.InstantMessage; +using OpenSim.Services.Connectors.Hypergrid; +using OpenSim.Server.Handlers.Hypergrid; + +namespace OpenSim.Region.CoreModules.Avatar.InstantMessage +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class HGMessageTransferModule : ISharedRegionModule, IMessageTransferModule, IInstantMessageSimConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected bool m_Enabled = false; + protected List m_Scenes = new List(); + + protected IInstantMessage m_IMService; + protected Dictionary m_UserLocationMap = new Dictionary(); + + public event UndeliveredMessage OnUndeliveredMessage; + + IUserManagement m_uMan; + IUserManagement UserManagementModule + { + get + { + if (m_uMan == null) + m_uMan = m_Scenes[0].RequestModuleInterface(); + return m_uMan; + } + } + + public virtual void Initialise(IConfigSource config) + { + IConfig cnf = config.Configs["Messaging"]; + if (cnf != null && cnf.GetString( + "MessageTransferModule", "MessageTransferModule") != Name) + { + m_log.Debug("[HG MESSAGE TRANSFER]: Disabled by configuration"); + return; + } + + InstantMessageServerConnector imServer = new InstantMessageServerConnector(config, MainServer.Instance, this); + m_IMService = imServer.GetService(); + m_Enabled = true; + } + + public virtual void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_Scenes) + { + m_log.DebugFormat("[HG MESSAGE TRANSFER]: Message transfer module {0} active", Name); + scene.RegisterModuleInterface(this); + m_Scenes.Add(scene); + } + } + + public virtual void PostInitialise() + { + if (!m_Enabled) + return; + + } + + public virtual void RegionLoaded(Scene scene) + { + } + + public virtual void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_Scenes) + { + m_Scenes.Remove(scene); + } + } + + public virtual void Close() + { + } + + public virtual string Name + { + get { return "HGMessageTransferModule"; } + } + + public virtual Type ReplaceableInterface + { + get { return null; } + } + + public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) + { + UUID toAgentID = new UUID(im.toAgentID); + + // Try root avatar only first + foreach (Scene scene in m_Scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { +// m_log.DebugFormat( +// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", +// toAgentID.ToString(), scene.RegionInfo.RegionName); + + ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; + if (!user.IsChildAgent) + { + // Local message +// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); + user.ControllingClient.SendInstantMessage(im); + + // Message sent + result(true); + return; + } + } + } + + // try child avatar second + foreach (Scene scene in m_Scenes) + { +// m_log.DebugFormat( +// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); + + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { + // Local message + ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; + +// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); + user.ControllingClient.SendInstantMessage(im); + + // Message sent + result(true); + return; + } + } + +// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); + // Is the user a local user? + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID); + string url = string.Empty; + PresenceInfo upd; + if (account == null) // foreign user + url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI"); + + Util.FireAndForget(delegate + { + bool success = m_IMService.OutgoingInstantMessage(im, url); + result(success); + }); + + return; + } + + protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID) + { + bool successful = false; + foreach (Scene scene in m_Scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { + ScenePresence user = + (ScenePresence)scene.Entities[toAgentID]; + + if (!user.IsChildAgent) + { + scene.EventManager.TriggerIncomingInstantMessage(gim); + successful = true; + } + } + } + if (!successful) + { + // If the message can't be delivered to an agent, it + // is likely to be a group IM. On a group IM, the + // imSessionID = toAgentID = group id. Raise the + // unhandled IM event to give the groups module + // a chance to pick it up. We raise that in a random + // scene, since the groups module is shared. + // + m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim); + } + + return successful; + } + + protected void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) + { + UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; + + // If this event has handlers, then an IM from an agent will be + // considered delivered. This will suppress the error message. + // + if (handlerUndeliveredMessage != null) + { + handlerUndeliveredMessage(im); + if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) + result(true); + else + result(false); + return; + } + + //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable"); + result(false); + } + + #region IInstantMessageSimConnector + public bool SendInstantMessage(GridInstantMessage im) + { + //m_log.DebugFormat("[XXX] Hook SendInstantMessage {0}", im.message); + UUID agentID = new UUID(im.toAgentID); + return SendIMToScene(im, agentID); + } + #endregion + + + } +} diff --git a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs new file mode 100644 index 0000000000..138313aedd --- /dev/null +++ b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs @@ -0,0 +1,280 @@ +/* + * 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.Reflection; + +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +using log4net; +using Nwc.XmlRpc; +using OpenMetaverse; + +namespace OpenSim.Server.Handlers.Hypergrid +{ + public class InstantMessageServerConnector : ServiceConnector + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private IInstantMessage m_IMService; + + public InstantMessageServerConnector(IConfigSource config, IHttpServer server) : + this(config, server, null) + { + } + + public InstantMessageServerConnector(IConfigSource config, IHttpServer server, IInstantMessageSimConnector simConnector) : + base(config, server, String.Empty) + { + IConfig gridConfig = config.Configs["HGInstantMessageService"]; + if (gridConfig != null) + { + string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty); + + Object[] args = new Object[] { config, simConnector }; + m_IMService = ServerUtils.LoadPlugin(serviceDll, args); + } + if (m_IMService == null) + throw new Exception("InstantMessage server connector cannot proceed because of missing service"); + + MainServer.Instance.AddXmlRPCHandler("grid_instant_message", ProcessInstantMessage, false); + + } + + public IInstantMessage GetService() + { + return m_IMService; + } + + protected virtual XmlRpcResponse ProcessInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient) + { + bool successful = false; + + try + { + // various rational defaults + UUID fromAgentID = UUID.Zero; + UUID toAgentID = UUID.Zero; + UUID imSessionID = UUID.Zero; + uint timestamp = 0; + string fromAgentName = ""; + string message = ""; + byte dialog = (byte)0; + bool fromGroup = false; + byte offline = (byte)0; + uint ParentEstateID = 0; + Vector3 Position = Vector3.Zero; + UUID RegionID = UUID.Zero; + byte[] binaryBucket = new byte[0]; + + float pos_x = 0; + float pos_y = 0; + float pos_z = 0; + //m_log.Info("Processing IM"); + + + Hashtable requestData = (Hashtable)request.Params[0]; + // Check if it's got all the data + if (requestData.ContainsKey("from_agent_id") + && requestData.ContainsKey("to_agent_id") && requestData.ContainsKey("im_session_id") + && requestData.ContainsKey("timestamp") && requestData.ContainsKey("from_agent_name") + && requestData.ContainsKey("message") && requestData.ContainsKey("dialog") + && requestData.ContainsKey("from_group") + && requestData.ContainsKey("offline") && requestData.ContainsKey("parent_estate_id") + && requestData.ContainsKey("position_x") && requestData.ContainsKey("position_y") + && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") + && requestData.ContainsKey("binary_bucket")) + { + // Do the easy way of validating the UUIDs + UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); + UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); + UUID.TryParse((string)requestData["im_session_id"], out imSessionID); + UUID.TryParse((string)requestData["region_id"], out RegionID); + + try + { + timestamp = (uint)Convert.ToInt32((string)requestData["timestamp"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + + fromAgentName = (string)requestData["from_agent_name"]; + message = (string)requestData["message"]; + if (message == null) + message = string.Empty; + + // Bytes don't transfer well over XMLRPC, so, we Base64 Encode them. + string requestData1 = (string)requestData["dialog"]; + if (string.IsNullOrEmpty(requestData1)) + { + dialog = 0; + } + else + { + byte[] dialogdata = Convert.FromBase64String(requestData1); + dialog = dialogdata[0]; + } + + if ((string)requestData["from_group"] == "TRUE") + fromGroup = true; + + string requestData2 = (string)requestData["offline"]; + if (String.IsNullOrEmpty(requestData2)) + { + offline = 0; + } + else + { + byte[] offlinedata = Convert.FromBase64String(requestData2); + offline = offlinedata[0]; + } + + try + { + ParentEstateID = (uint)Convert.ToInt32((string)requestData["parent_estate_id"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + + try + { + pos_x = (uint)Convert.ToInt32((string)requestData["position_x"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + try + { + pos_y = (uint)Convert.ToInt32((string)requestData["position_y"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + try + { + pos_z = (uint)Convert.ToInt32((string)requestData["position_z"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + + Position = new Vector3(pos_x, pos_y, pos_z); + + string requestData3 = (string)requestData["binary_bucket"]; + if (string.IsNullOrEmpty(requestData3)) + { + binaryBucket = new byte[0]; + } + else + { + binaryBucket = Convert.FromBase64String(requestData3); + } + + // Create a New GridInstantMessageObject the the data + GridInstantMessage gim = new GridInstantMessage(); + gim.fromAgentID = fromAgentID.Guid; + gim.fromAgentName = fromAgentName; + gim.fromGroup = fromGroup; + gim.imSessionID = imSessionID.Guid; + gim.RegionID = UUID.Zero.Guid; // RegionID.Guid; + gim.timestamp = timestamp; + gim.toAgentID = toAgentID.Guid; + gim.message = message; + gim.dialog = dialog; + gim.offline = offline; + gim.ParentEstateID = ParentEstateID; + gim.Position = Position; + gim.binaryBucket = binaryBucket; + + successful = m_IMService.IncomingInstantMessage(gim); + + } + } + catch (Exception e) + { + m_log.Error("[INSTANT MESSAGE]: Caught unexpected exception:", e); + successful = false; + } + + //Send response back to region calling if it was successful + // calling region uses this to know when to look up a user's location again. + XmlRpcResponse resp = new XmlRpcResponse(); + Hashtable respdata = new Hashtable(); + if (successful) + respdata["success"] = "TRUE"; + else + respdata["success"] = "FALSE"; + resp.Value = respdata; + + return resp; + } + + } +} diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index e51fe0bc26..942d96073b 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -52,6 +52,7 @@ namespace OpenSim.Server.Handlers.Hypergrid // MethodBase.GetCurrentMethod().DeclaringType); private IUserAgentService m_HomeUsersService; + private string[] m_AuthorizedCallers; public UserAgentServerConnector(IConfigSource config, IHttpServer server) : this(config, server, null) @@ -75,6 +76,10 @@ namespace OpenSim.Server.Handlers.Hypergrid string loginServerIP = gridConfig.GetString("LoginServerIP", "127.0.0.1"); bool proxy = gridConfig.GetBoolean("HasProxy", false); + string csv = gridConfig.GetString("AuthorizedCallers", "127.0.0.1"); + csv = csv.Replace(" ", ""); + m_AuthorizedCallers = csv.Split(','); + server.AddXmlRPCHandler("agent_is_coming_home", AgentIsComingHome, false); server.AddXmlRPCHandler("get_home_region", GetHomeRegion, false); server.AddXmlRPCHandler("verify_agent", VerifyAgent, false); @@ -85,6 +90,8 @@ namespace OpenSim.Server.Handlers.Hypergrid server.AddXmlRPCHandler("get_online_friends", GetOnlineFriends, false); server.AddXmlRPCHandler("get_server_urls", GetServerURLs, false); + server.AddXmlRPCHandler("locate_user", LocateUser, false); + server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); } @@ -306,5 +313,46 @@ namespace OpenSim.Server.Handlers.Hypergrid } + /// + /// Locates the user. + /// This is a sensitive operation, only authorized IP addresses can perform it. + /// + /// + /// + /// + public XmlRpcResponse LocateUser(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + bool authorized = false; + foreach (string s in m_AuthorizedCallers) + if (s == remoteClient.Address.ToString()) + { + authorized = true; + break; + } + + if (authorized) + { + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + string url = m_HomeUsersService.LocateUser(userID); + if (url != string.Empty) + hash["URL"] = url; + } + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } } } diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 265bacf33e..50036b36e8 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -560,6 +560,64 @@ namespace OpenSim.Services.Connectors.Hypergrid return serverURLs; } + public string LocateUser(UUID userID) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + + IList paramList = new ArrayList(); + paramList.Add(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 (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return url; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} 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 (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response."); + reason = "Exception: " + e.Message; + } + + return url; + } + private bool GetBoolResponse(XmlRpcRequest request, out string reason) { //m_log.Debug("[USER AGENT CONNECTOR]: GetBoolResponse from/to " + m_ServerURL); diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs new file mode 100644 index 0000000000..65ee7c7aeb --- /dev/null +++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs @@ -0,0 +1,129 @@ +/* + * 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.Reflection; + +using OpenMetaverse; +using Nwc.XmlRpc; +using log4net; + +using OpenSim.Framework; + +namespace OpenSim.Services.Connectors.InstantMessage +{ + public class InstantMessageServiceConnector + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// This actually does the XMLRPC Request + /// + /// URL we pull the data out of to send the request to + /// The Instant Message + /// Bool if the message was successfully delivered at the other side. + public static bool SendInstantMessage(string url, GridInstantMessage im) + { + Hashtable xmlrpcdata = ConvertGridInstantMessageToXMLRPC(im); + xmlrpcdata["region_handle"] = 0; + + ArrayList SendParams = new ArrayList(); + SendParams.Add(xmlrpcdata); + XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams); + try + { + + XmlRpcResponse GridResp = GridReq.Send(url, 3000); + + Hashtable responseData = (Hashtable)GridResp.Value; + + if (responseData.ContainsKey("success")) + { + if ((string)responseData["success"] == "TRUE") + { + m_log.DebugFormat("[XXX] Success"); + return true; + } + else + { + m_log.DebugFormat("[XXX] Fail"); + return false; + } + } + else + { + return false; + } + } + catch (WebException e) + { + m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond " + e.ToString(), url); + } + + return false; + } + + /// + /// Takes a GridInstantMessage and converts it into a Hashtable for XMLRPC + /// + /// The GridInstantMessage object + /// Hashtable containing the XMLRPC request + protected static Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg) + { + Hashtable gim = new Hashtable(); + gim["from_agent_id"] = msg.fromAgentID.ToString(); + // Kept for compatibility + gim["from_agent_session"] = UUID.Zero.ToString(); + gim["to_agent_id"] = msg.toAgentID.ToString(); + gim["im_session_id"] = msg.imSessionID.ToString(); + gim["timestamp"] = msg.timestamp.ToString(); + gim["from_agent_name"] = msg.fromAgentName; + gim["message"] = msg.message; + byte[] dialogdata = new byte[1]; dialogdata[0] = msg.dialog; + gim["dialog"] = Convert.ToBase64String(dialogdata, Base64FormattingOptions.None); + + if (msg.fromGroup) + gim["from_group"] = "TRUE"; + else + gim["from_group"] = "FALSE"; + byte[] offlinedata = new byte[1]; offlinedata[0] = msg.offline; + gim["offline"] = Convert.ToBase64String(offlinedata, Base64FormattingOptions.None); + gim["parent_estate_id"] = msg.ParentEstateID.ToString(); + gim["position_x"] = msg.Position.X.ToString(); + gim["position_y"] = msg.Position.Y.ToString(); + gim["position_z"] = msg.Position.Z.ToString(); + gim["region_id"] = msg.RegionID.ToString(); + gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket, Base64FormattingOptions.None); + return gim; + } + + } +} diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs new file mode 100644 index 0000000000..6178ca1d7b --- /dev/null +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -0,0 +1,311 @@ +/* + * 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 OpenSim.Framework; +using OpenSim.Services.Connectors.Friends; +using OpenSim.Services.Connectors.Hypergrid; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.InstantMessage; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using OpenSim.Server.Base; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; + +using OpenMetaverse; +using log4net; +using Nini.Config; + +namespace OpenSim.Services.HypergridService +{ + /// + /// Inter-grid IM + /// + public class HGInstantMessageService : IInstantMessage + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours + + static bool m_Initialized = false; + + protected static IGridService m_GridService; + protected static IPresenceService m_PresenceService; + protected static IUserAgentService m_UserAgentService; + + protected static IInstantMessageSimConnector m_IMSimConnector; + + protected Dictionary m_UserLocationMap = new Dictionary(); + private ExpiringCache m_RegionCache; + + public HGInstantMessageService(IConfigSource config) + : this(config, null) + { + } + + public HGInstantMessageService(IConfigSource config, IInstantMessageSimConnector imConnector) + { + if (imConnector != null) + m_IMSimConnector = imConnector; + + if (!m_Initialized) + { + m_Initialized = true; + + m_log.DebugFormat("[HG IM SERVICE]: Starting..."); + + IConfig serverConfig = config.Configs["HGInstantMessageService"]; + if (serverConfig == null) + throw new Exception(String.Format("No section HGInstantMessageService in config file")); + + string gridService = serverConfig.GetString("GridService", String.Empty); + string presenceService = serverConfig.GetString("PresenceService", String.Empty); + string userAgentService = serverConfig.GetString("UserAgentService", String.Empty); + + if (gridService == string.Empty || presenceService == string.Empty) + throw new Exception(String.Format("Incomplete specifications, InstantMessage Service cannot function.")); + + Object[] args = new Object[] { config }; + m_GridService = ServerUtils.LoadPlugin(gridService, args); + m_PresenceService = ServerUtils.LoadPlugin(presenceService, args); + m_UserAgentService = ServerUtils.LoadPlugin(userAgentService, args); + + m_RegionCache = new ExpiringCache(); + + } + } + + public bool IncomingInstantMessage(GridInstantMessage im) + { + m_log.DebugFormat("[HG IM SERVICE]: Received message {0} from {1} to {2}", im.message, im.fromAgentID, im.toAgentID); + UUID toAgentID = new UUID(im.toAgentID); + + if (m_IMSimConnector != null) + { + m_log.DebugFormat("[XXX] SendIMToRegion local im connector"); + return m_IMSimConnector.SendInstantMessage(im); + } + else + return TrySendInstantMessage(im, "", true); + } + + public bool OutgoingInstantMessage(GridInstantMessage im, string url) + { + m_log.DebugFormat("[HG IM SERVICE]: Sending message {0} from {1} to {2}@{3}", im.message, im.fromAgentID, im.toAgentID, url); + if (url != string.Empty) + return TrySendInstantMessage(im, url, true); + else + { + PresenceInfo upd = new PresenceInfo(); + upd.RegionID = UUID.Zero; + return TrySendInstantMessage(im, upd, true); + } + } + + protected bool TrySendInstantMessage(GridInstantMessage im, object previousLocation, bool firstTime) + { + UUID toAgentID = new UUID(im.toAgentID); + + PresenceInfo upd = null; + string url = string.Empty; + + bool lookupAgent = false; + + lock (m_UserLocationMap) + { + if (m_UserLocationMap.ContainsKey(toAgentID)) + { + object o = m_UserLocationMap[toAgentID]; + if (o is PresenceInfo) + upd = (PresenceInfo)o; + else if (o is string) + url = (string)o; + + // We need to compare the current location with the previous + // or the recursive loop will never end because it will never try to lookup the agent again + if (!firstTime) + { + lookupAgent = true; + } + } + else + { + lookupAgent = true; + } + } + + m_log.DebugFormat("[XXX] Neeed lookup ? {0}", (lookupAgent ? "yes" : "no")); + + // Are we needing to look-up an agent? + if (lookupAgent) + { + bool isPresent = false; + // Non-cached user agent lookup. + PresenceInfo[] presences = m_PresenceService.GetAgents(new string[] { toAgentID.ToString() }); + if (presences != null && presences.Length > 0) + { + foreach (PresenceInfo p in presences) + { + if (p.RegionID != UUID.Zero) + { + upd = p; + break; + } + else + isPresent = true; + } + } + + if (upd == null && isPresent) + { + // Let's check with the UAS if the user is elsewhere + url = m_UserAgentService.LocateUser(toAgentID); + } + + if (upd != null || url != string.Empty) + { + // check if we've tried this before.. + // This is one way to end the recursive loop + // + if (!firstTime && ((previousLocation is PresenceInfo && upd != null && upd.RegionID == ((PresenceInfo)previousLocation).RegionID) || + (previousLocation is string && previousLocation.Equals(url)))) + { + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + m_log.DebugFormat("[XXX] Fail 1 {0} {1}", previousLocation, url); + + return false; + } + } + } + + if (upd != null) + { + // ok, the user is around somewhere. Let's send back the reply with "success" + // even though the IM may still fail. Just don't keep the caller waiting for + // the entire time we're trying to deliver the IM + return SendIMToRegion(upd, im, toAgentID); + } + else if (url != string.Empty) + { + // ok, the user is around somewhere. Let's send back the reply with "success" + // even though the IM may still fail. Just don't keep the caller waiting for + // the entire time we're trying to deliver the IM + return ForwardIMToGrid(url, im, toAgentID); + } + else if (firstTime && previousLocation is string && (string)previousLocation != string.Empty) + { + return ForwardIMToGrid((string)previousLocation, im, toAgentID); + } + else + m_log.DebugFormat("[HG IM SERVICE]: Unable to locate user {0}", toAgentID); + return false; + } + + bool SendIMToRegion(PresenceInfo upd, GridInstantMessage im, UUID toAgentID) + { + bool imresult = false; + GridRegion reginfo = null; + if (!m_RegionCache.TryGetValue(upd.RegionID, out reginfo)) + { + reginfo = m_GridService.GetRegionByUUID(UUID.Zero /*!!!*/, upd.RegionID); + if (reginfo != null) + m_RegionCache.AddOrUpdate(upd.RegionID, reginfo, CACHE_EXPIRATION_SECONDS); + } + + if (reginfo != null) + imresult = InstantMessageServiceConnector.SendInstantMessage(reginfo.ServerURI, im); + else + return false; + + if (imresult) + { + // IM delivery successful, so store the Agent's location in our local cache. + lock (m_UserLocationMap) + { + if (m_UserLocationMap.ContainsKey(toAgentID)) + { + m_UserLocationMap[toAgentID] = upd; + } + else + { + m_UserLocationMap.Add(toAgentID, upd); + } + } + return true; + } + else + { + // try again, but lookup user this time. + // Warning, this must call the Async version + // of this method or we'll be making thousands of threads + // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync + // The version that spawns the thread is SendGridInstantMessageViaXMLRPC + + // This is recursive!!!!! + return TrySendInstantMessage(im, upd, false); + } + } + + bool ForwardIMToGrid(string url, GridInstantMessage im, UUID toAgentID) + { + if (InstantMessageServiceConnector.SendInstantMessage(url, im)) + { + // IM delivery successful, so store the Agent's location in our local cache. + lock (m_UserLocationMap) + { + if (m_UserLocationMap.ContainsKey(toAgentID)) + { + m_UserLocationMap[toAgentID] = url; + } + else + { + m_UserLocationMap.Add(toAgentID, url); + } + } + + return true; + } + else + { + // try again, but lookup user this time. + // Warning, this must call the Async version + // of this method or we'll be making thousands of threads + // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync + // The version that spawns the thread is SendGridInstantMessageViaXMLRPC + + // This is recursive!!!!! + return TrySendInstantMessage(im, url, false); + } + + } + } +} diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index e63f941cc3..59ad043cef 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -474,6 +474,17 @@ namespace OpenSim.Services.HypergridService return new Dictionary(); } + + public string LocateUser(UUID userID) + { + foreach (TravelingAgentInfo t in m_TravelingAgents.Values) + { + if (t.UserID == userID) + return t.GridExternalName; + } + + return string.Empty; + } } class TravelingAgentInfo diff --git a/OpenSim/Services/Interfaces/IGatekeeperService.cs b/OpenSim/Services/Interfaces/IGatekeeperService.cs index f1860cce58..ffab9eadcc 100644 --- a/OpenSim/Services/Interfaces/IGatekeeperService.cs +++ b/OpenSim/Services/Interfaces/IGatekeeperService.cs @@ -56,6 +56,8 @@ namespace OpenSim.Services.Interfaces GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); Dictionary GetServerURLs(UUID userID); + string LocateUser(UUID userID); + void StatusNotification(List friends, UUID userID, bool online); List GetOnlineFriends(UUID userID, List friends); @@ -63,4 +65,10 @@ namespace OpenSim.Services.Interfaces bool VerifyAgent(UUID sessionID, string token); bool VerifyClient(UUID sessionID, string reportedIP); } + + public interface IInstantMessage + { + bool IncomingInstantMessage(GridInstantMessage im); + bool OutgoingInstantMessage(GridInstantMessage im, string url); + } } diff --git a/OpenSim/Services/Interfaces/ISimulatorSocialService.cs b/OpenSim/Services/Interfaces/ISimulatorSocialService.cs index 0b7aefcf35..df9e7e7919 100644 --- a/OpenSim/Services/Interfaces/ISimulatorSocialService.cs +++ b/OpenSim/Services/Interfaces/ISimulatorSocialService.cs @@ -37,4 +37,9 @@ namespace OpenSim.Services.Interfaces { bool StatusNotify(UUID userID, UUID friendID, bool online); } + + public interface IInstantMessageSimConnector + { + bool SendInstantMessage(GridInstantMessage im); + } } diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index 6cd24b09fc..cd2d7a7bac 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -32,6 +32,9 @@ AuthenticationServiceInConnector = true SimulationServiceInConnector = true +[Messaging] + MessageTransferModule = HGMessageTransferModule + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" @@ -148,6 +151,13 @@ LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService" UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" +[HGInstantMessageService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.GridService.dll:GridService" + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + + ;; This should always be the very last thing on this file [Includes] Include-Common = "config-include/StandaloneCommon.ini" From 587b17e23b3919377f4f1af08e2a59e8eec69ef6 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 25 May 2011 12:37:37 -0700 Subject: [PATCH 054/186] HG: Renamed, shuffled some interfaces around. Move them all to IHypergridServices. --- ...keeperService.cs => IHypergridServices.cs} | 9 ++++ .../Interfaces/ISimulatorSocialService.cs | 45 ------------------- 2 files changed, 9 insertions(+), 45 deletions(-) rename OpenSim/Services/Interfaces/{IGatekeeperService.cs => IHypergridServices.cs} (93%) delete mode 100644 OpenSim/Services/Interfaces/ISimulatorSocialService.cs diff --git a/OpenSim/Services/Interfaces/IGatekeeperService.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs similarity index 93% rename from OpenSim/Services/Interfaces/IGatekeeperService.cs rename to OpenSim/Services/Interfaces/IHypergridServices.cs index ffab9eadcc..3ab6d4f88b 100644 --- a/OpenSim/Services/Interfaces/IGatekeeperService.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -71,4 +71,13 @@ namespace OpenSim.Services.Interfaces bool IncomingInstantMessage(GridInstantMessage im); bool OutgoingInstantMessage(GridInstantMessage im, string url); } + public interface IFriendsSimConnector + { + bool StatusNotify(UUID userID, UUID friendID, bool online); + } + + public interface IInstantMessageSimConnector + { + bool SendInstantMessage(GridInstantMessage im); + } } diff --git a/OpenSim/Services/Interfaces/ISimulatorSocialService.cs b/OpenSim/Services/Interfaces/ISimulatorSocialService.cs deleted file mode 100644 index df9e7e7919..0000000000 --- a/OpenSim/Services/Interfaces/ISimulatorSocialService.cs +++ /dev/null @@ -1,45 +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 OpenSim.Framework; -using OpenMetaverse; - -using GridRegion = OpenSim.Services.Interfaces.GridRegion; - -namespace OpenSim.Services.Interfaces -{ - public interface IFriendsSimConnector - { - bool StatusNotify(UUID userID, UUID friendID, bool online); - } - - public interface IInstantMessageSimConnector - { - bool SendInstantMessage(GridInstantMessage im); - } -} From 6f4d079fc5b28ef6657fe2baf6ef305a54e674d2 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 26 May 2011 01:27:01 +0100 Subject: [PATCH 055/186] Add a --noassets option to "save oar". This switch stops any assets being saved in the oar. This can be useful if you're using OAR to backup regions and you know you'll always have the original asset database available. --- OpenSim/Region/Application/OpenSim.cs | 9 +- .../ArchiveWriteRequestPreparation.cs | 81 ++++++++++------- .../World/Archiver/ArchiverModule.cs | 8 +- .../World/Archiver/Tests/ArchiverTests.cs | 91 ++++++++++++++++++- .../Interfaces/IRegionArchiverModule.cs | 25 +++-- 5 files changed, 167 insertions(+), 47 deletions(-) diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 39004d4028..8add2afb66 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -267,12 +267,13 @@ namespace OpenSim m_console.Commands.AddCommand("region", false, "save oar", //"save oar [-v|--version=] [-p|--profile=] []", - "save oar [-p|--profile=] []", + "save oar [-p|--profile=] [--noassets] []", "Save a region's data to an OAR archive.", // "-v|--version= generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine - "-p|--profile= adds the url of the profile service to the saved user information" + Environment.NewLine - + "The OAR path must be a filesystem path." - + " If this is not given then the oar is saved to region.oar in the current directory.", + "-p|--profile= adds the url of the profile service to the saved user information." + Environment.NewLine + + " The OAR path must be a filesystem path." + + " If this is not given then the oar is saved to region.oar in the current directory." + Environment.NewLine + + "--noassets stops assets being saved to the OAR.", SaveOar); m_console.Commands.AddCommand("region", false, "edit scale", diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 597b7809e5..6a86dfe2fd 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -58,7 +58,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// The maximum major version of OAR that we can write. /// - public static int MAX_MAJOR_VERSION = 0; + public static int MAX_MAJOR_VERSION = 0; + + /// + /// Determine whether this oar will save assets. Default is true. + /// + public bool SaveAssets { get; set; } protected Scene m_scene; protected Stream m_saveStream; @@ -73,10 +78,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// If there was a problem opening a stream for the file specified by the savePath /// - public ArchiveWriteRequestPreparation(Scene scene, string savePath, Guid requestId) + public ArchiveWriteRequestPreparation(Scene scene, string savePath, Guid requestId) : this(scene, requestId) { - m_scene = scene; - try { m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress); @@ -86,10 +89,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.ErrorFormat( "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); - m_log.Error(e); + m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); } - - m_requestId = requestId; } /// @@ -98,11 +99,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// The stream to which to save data. /// The id associated with this request - public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream, Guid requestId) + public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId) + { + m_saveStream = saveStream; + } + + protected ArchiveWriteRequestPreparation(Scene scene, Guid requestId) { m_scene = scene; - m_saveStream = saveStream; m_requestId = requestId; + + SaveAssets = true; } /// @@ -111,22 +118,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// if there was an io problem with creating the file public void ArchiveRegion(Dictionary options) { + if (options.ContainsKey("noassets") && (bool)options["noassets"]) + SaveAssets = false; + try { Dictionary assetUuids = new Dictionary(); EntityBase[] entities = m_scene.GetEntities(); List sceneObjects = new List(); - - /* - foreach (ILandObject lo in m_scene.LandChannel.AllParcels()) - { - if (name == lo.LandData.Name) - { - // This is the parcel we want - } - } - */ // Filter entities so that we only have scene objects. // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods @@ -141,17 +141,24 @@ namespace OpenSim.Region.CoreModules.World.Archiver sceneObjects.Add((SceneObjectGroup)entity); } } - - UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); - - foreach (SceneObjectGroup sceneObject in sceneObjects) + + if (SaveAssets) { - assetGatherer.GatherAssetUuids(sceneObject, assetUuids); + UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); + + foreach (SceneObjectGroup sceneObject in sceneObjects) + { + assetGatherer.GatherAssetUuids(sceneObject, assetUuids); + } + + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", + sceneObjects.Count, assetUuids.Count); + } + else + { + m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); } - - m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", - sceneObjects.Count, assetUuids.Count); // Make sure that we also request terrain texture assets RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; @@ -187,11 +194,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); - - new AssetsRequest( - new AssetsArchiver(archiveWriter), assetUuids, - m_scene.AssetService, m_scene.UserAccountService, - m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets).Execute(); + + if (SaveAssets) + new AssetsRequest( + new AssetsArchiver(archiveWriter), assetUuids, + m_scene.AssetService, m_scene.UserAccountService, + m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets).Execute(); + else + awre.ReceivedAllAssets(new List(), new List()); } catch (Exception) { @@ -204,7 +214,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// Create the control file for the most up to date archive /// /// - public static string CreateControlFile(Dictionary options) + public string CreateControlFile(Dictionary options) { int majorVersion = MAX_MAJOR_VERSION, minorVersion = 6; // @@ -258,6 +268,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); xtw.WriteElementString("id", UUID.Random().ToString()); xtw.WriteEndElement(); + + xtw.WriteElementString("assets_included", SaveAssets.ToString()); + xtw.WriteEndElement(); xtw.Flush(); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 9277c594f0..08eb80cc2e 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -127,6 +127,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver OptionSet ops = new OptionSet(); // ops.Add("v|version=", delegate(string v) { options["version"] = v; }); ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); + ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); List mainParams = ops.Parse(cmdparams); @@ -160,7 +161,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver public void ArchiveRegion(Stream saveStream, Guid requestId) { - new ArchiveWriteRequestPreparation(m_scene, saveStream, requestId).ArchiveRegion(new Dictionary()); + ArchiveRegion(saveStream, requestId, new Dictionary()); + } + + public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary options) + { + new ArchiveWriteRequestPreparation(m_scene, saveStream, requestId).ArchiveRegion(options); } public void DearchiveRegion(string loadPath) diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 2eb2861005..34e2e23a01 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -211,6 +211,89 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // TODO: Test presence of more files and contents of files. } + /// + /// Test saving an OpenSim Region Archive with the no assets option + /// + [Test] + public void TestSaveOarNoAssets() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + SceneObjectPart part1 = CreateSceneObjectPart1(); + SceneObjectGroup sog1 = new SceneObjectGroup(part1); + m_scene.AddNewSceneObject(sog1, false); + + SceneObjectPart part2 = CreateSceneObjectPart2(); + + AssetNotecard nc = new AssetNotecard(); + nc.BodyText = "Hello World!"; + nc.Encode(); + UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); + UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); + AssetBase ncAsset + = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); + m_scene.AssetService.Store(ncAsset); + SceneObjectGroup sog2 = new SceneObjectGroup(part2); + TaskInventoryItem ncItem + = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; + part2.Inventory.AddInventoryItem(ncItem, true); + + m_scene.AddNewSceneObject(sog2, false); + + MemoryStream archiveWriteStream = new MemoryStream(); + + Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); + + Dictionary options = new Dictionary(); + options.Add("noassets", true); + m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); + //AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer; + //while (assetServer.HasWaitingRequests()) + // assetServer.ProcessNextRequest(); + + // Don't wait for completion - with --noassets save oar happens synchronously +// Monitor.Wait(this, 60000); + + Assert.That(m_lastRequestId, Is.EqualTo(requestId)); + + byte[] archive = archiveWriteStream.ToArray(); + MemoryStream archiveReadStream = new MemoryStream(archive); + TarArchiveReader tar = new TarArchiveReader(archiveReadStream); + + List foundPaths = new List(); + List expectedPaths = new List(); + expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog1)); + expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2)); + + string filePath; + TarArchiveReader.TarEntryType tarEntryType; + + byte[] data = tar.ReadEntry(out filePath, out tarEntryType); + Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); + + ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); + arr.LoadControlFile(filePath, data); + + Assert.That(arr.ControlFileLoaded, Is.True); + + while (tar.ReadEntry(out filePath, out tarEntryType) != null) + { + if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + { + Assert.Fail("Asset was found in saved oar of TestSaveOarNoAssets()"); + } + else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) + { + foundPaths.Add(filePath); + } + } + + Assert.That(foundPaths, Is.EquivalentTo(expectedPaths)); + + // TODO: Test presence of more files and contents of files. + } + /// /// Test loading an OpenSim Region Archive. /// @@ -230,7 +313,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // upset load tar.WriteDir(ArchiveConstants.TERRAINS_PATH); - tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestPreparation.CreateControlFile(new Dictionary())); + tar.WriteFile( + ArchiveConstants.CONTROL_FILE_PATH, + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); SceneObjectPart part1 = CreateSceneObjectPart1(); SceneObjectGroup object1 = new SceneObjectGroup(part1); @@ -331,7 +416,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); tar.WriteDir(ArchiveConstants.TERRAINS_PATH); - tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestPreparation.CreateControlFile(new Dictionary())); + tar.WriteFile( + ArchiveConstants.CONTROL_FILE_PATH, + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); RegionSettings rs = new RegionSettings(); rs.AgentLimit = 17; diff --git a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs index d8229de5a5..3fafc47648 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs @@ -52,31 +52,44 @@ namespace OpenSim.Region.Framework.Interfaces /// /// Archive the region to the given path /// - /// + /// /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to /// the EventManager.OnOarFileSaved event. - /// + /// /// /// If supplied, this request Id is later returned in the saved event + /// Options for the save void ArchiveRegion(string savePath, Guid requestId, Dictionary options); /// /// Archive the region to a stream. /// - /// + /// /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to /// the EventManager.OnOarFileSaved event. - /// + /// /// /// If supplied, this request Id is later returned in the saved event void ArchiveRegion(Stream saveStream, Guid requestId); + /// + /// Archive the region to a stream. + /// + /// + /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to + /// the EventManager.OnOarFileSaved event. + /// + /// + /// If supplied, this request Id is later returned in the saved event + /// Options for the save + void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary options); + /// /// Dearchive the given region archive. This replaces the existing scene. /// - /// + /// /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. - /// + /// /// void DearchiveRegion(string loadPath); From ab855e6f8dbb8edc843aee7c7e82d3fbddb9c4d8 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 26 May 2011 01:32:12 +0100 Subject: [PATCH 056/186] fix bug where outfit folder links could not be deleted --- OpenSim/Services/InventoryService/XInventoryService.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 2282ee85bc..58c59ebb93 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -40,9 +40,9 @@ namespace OpenSim.Services.InventoryService { public class XInventoryService : ServiceBase, IInventoryService { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = +// LogManager.GetLogger( +// MethodBase.GetCurrentMethod().DeclaringType); protected IXInventoryData m_Database; protected bool m_AllowDelete = true; @@ -424,7 +424,7 @@ namespace OpenSim.Services.InventoryService { if (!m_Database.DeleteItems( new string[] { "inventoryID", "assetType" }, - new string[] { id.ToString(), ((sbyte)AssetType.Link).ToString() })); + new string[] { id.ToString(), ((sbyte)AssetType.Link).ToString() })) { m_Database.DeleteItems( new string[] { "inventoryID", "assetType" }, From c7e46e8a51de7d137182956f1ec033250edc0da5 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 26 May 2011 01:37:15 +0100 Subject: [PATCH 057/186] Bump OAR file format version up to 0.7 for this development cycle. This adds a true|false element to the oar control file, though this is not used on reloading at this time. This addition is backward compatible with previous opensim releases --- .../World/Archiver/ArchiveWriteRequestPreparation.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 6a86dfe2fd..3d073bf51b 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver public class ArchiveWriteRequestPreparation { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - + /// /// The minimum major version of OAR that we can write. /// @@ -216,7 +216,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// public string CreateControlFile(Dictionary options) { - int majorVersion = MAX_MAJOR_VERSION, minorVersion = 6; + int majorVersion = MAX_MAJOR_VERSION, minorVersion = 7; // // if (options.ContainsKey("version")) // { From 3270f4353e0a2bded9361a72526ba673e6266cc1 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 26 May 2011 02:22:52 +0100 Subject: [PATCH 058/186] Add --noassets option for "save iar" Like "save oar", this saves an iar without assets This can be useful for backup when you know the required assets will still be present (e.g. you're backing up the assets db separately). This also bumps the iar format version to 0.3 and 1.2 respectively. 0.3 is backward compatible with previous opensim versions 1.2 is used if the --profile switch is specified. It is only compatible with 0.7.1 presently. --- .../Archiver/InventoryArchiveWriteRequest.cs | 45 ++++++-- .../Archiver/InventoryArchiverModule.cs | 14 ++- .../Archiver/Tests/InventoryArchiverTests.cs | 104 +++++++++++++++++- .../ArchiveWriteRequestPreparation.cs | 2 +- 4 files changed, 146 insertions(+), 19 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index c039b5a387..b5272ad151 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -46,6 +46,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// + /// Determine whether this archive will save assets. Default is true. + /// + public bool SaveAssets { get; set; } + /// /// Used to select all inventory nodes in a folder but not the folder itself /// @@ -112,6 +117,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_invPath = invPath; m_saveStream = saveStream; m_assetGatherer = new UuidGatherer(m_scene.AssetService); + + SaveAssets = true; } protected void ReceivedAllAssets(ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) @@ -150,7 +157,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService); m_archiveWriter.WriteFile(filename, serialization); - m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); + if (SaveAssets) + m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); } /// @@ -195,6 +203,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// public void Execute(Dictionary options, IUserAccountService userAccountService) { + if (options.ContainsKey("noassets") && (bool)options["noassets"]) + SaveAssets = false; + try { InventoryFolderBase inventoryFolder = null; @@ -285,12 +296,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // Don't put all this profile information into the archive right now. //SaveUsers(); - - new AssetsRequest( - new AssetsArchiver(m_archiveWriter), - m_assetUuids, m_scene.AssetService, - m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, - options, ReceivedAllAssets).Execute(); + + if (SaveAssets) + { + m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); + + new AssetsRequest( + new AssetsArchiver(m_archiveWriter), + m_assetUuids, m_scene.AssetService, + m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, + options, ReceivedAllAssets).Execute(); + } + else + { + m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); + + ReceivedAllAssets(new List(), new List()); + } } catch (Exception) { @@ -387,19 +409,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// /// - public static string CreateControlFile(Dictionary options) + public string CreateControlFile(Dictionary options) { int majorVersion, minorVersion; if (options.ContainsKey("profile")) { majorVersion = 1; - minorVersion = 1; + minorVersion = 2; } else { majorVersion = 0; - minorVersion = 2; + minorVersion = 3; } m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); @@ -411,6 +433,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver xtw.WriteStartElement("archive"); xtw.WriteAttributeString("major_version", majorVersion.ToString()); xtw.WriteAttributeString("minor_version", minorVersion.ToString()); + + xtw.WriteElementString("assets_included", SaveAssets.ToString()); + xtw.WriteEndElement(); xtw.Flush(); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 576a154719..e0b02aac46 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -122,7 +122,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver scene.AddCommand( this, "save iar", - "save iar [--p|-profile=] [] [--v|-verbose]", + "save iar [--p|-profile=] [--noassets] [] [--v|-verbose]", "Save user inventory archive (IAR).", " is the user's first name." + Environment.NewLine + " is the user's last name." + Environment.NewLine @@ -130,6 +130,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver + "-p|--profile= adds the url of the profile service to the saved user information." + Environment.NewLine + "-c|--creators preserves information about foreign creators." + Environment.NewLine + "-v|--verbose extra debug messages." + Environment.NewLine + + "--noassets stops assets being saved to the IAR." + " is the filesystem path at which to save the IAR." + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), HandleSaveInvConsoleCommand); @@ -398,6 +399,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; }); ops.Add("c|creators", delegate(string v) { options["creators"] = v; }); + ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); List mainParams = ops.Parse(cmdparams); @@ -406,7 +408,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (mainParams.Count < 6) { m_log.Error( - "[INVENTORY ARCHIVER]: usage is save iar [--p|-profile=] []"); + "[INVENTORY ARCHIVER]: usage is save iar [--p|-profile=] [--noassets] []"); return; } @@ -423,16 +425,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_log.InfoFormat( "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", savePath, invPath, firstName, lastName); - + + lock (m_pendingConsoleSaves) + m_pendingConsoleSaves.Add(id); + ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, options); } catch (InventoryArchiverException e) { m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); } - - lock (m_pendingConsoleSaves) - m_pendingConsoleSaves.Add(id); } private void SaveInvConsoleCommandCompleted( diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index d97311ab2b..ae3ab21b18 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -123,11 +123,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests } /// - /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive + /// Test saving a single inventory item to an IAR /// (subject to change since there is no fixed format yet). /// [Test] - public void TestSaveItemToIarV0_1() + public void TestSaveItemToIar() { TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); @@ -211,6 +211,106 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests } } +// Assert.That(gotControlFile, Is.True, "No control file in archive"); + Assert.That(gotObject1File, Is.True, "No item1 file in archive"); +// Assert.That(gotObject2File, Is.True, "No object2 file in archive"); + + // TODO: Test presence of more files and contents of files. + } + + /// + /// Test saving a single inventory item to an IAR without its asset + /// + [Test] + public void TestSaveItemToIarNoAssets() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + string userPassword = "troll"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); + + // Create asset + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50); + + UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); + AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); + m_scene.AssetService.Store(asset1); + + // Create item + UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); + string item1Name = "My Little Dog"; + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = item1Name; + item1.AssetID = asset1.FullID; + item1.ID = item1Id; + InventoryFolderBase objsFolder + = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, userId, "Objects")[0]; + item1.Folder = objsFolder.ID; + m_scene.AddInventoryItem(item1); + + MemoryStream archiveWriteStream = new MemoryStream(); + + Dictionary options = new Dictionary(); + options.Add("noassets", true); + + // When we're not saving assets, archiving is being done synchronously. + m_archiverModule.ArchiveInventory( + Guid.NewGuid(), userFirstName, userLastName, "Objects/" + item1Name, userPassword, archiveWriteStream, options); + + byte[] archive = archiveWriteStream.ToArray(); + MemoryStream archiveReadStream = new MemoryStream(archive); + TarArchiveReader tar = new TarArchiveReader(archiveReadStream); + + //bool gotControlFile = false; + bool gotObject1File = false; + //bool gotObject2File = false; + string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); + string expectedObject1FilePath = string.Format( + "{0}{1}", + ArchiveConstants.INVENTORY_PATH, + expectedObject1FileName); + + string filePath; + TarArchiveReader.TarEntryType tarEntryType; + +// Console.WriteLine("Reading archive"); + + while (tar.ReadEntry(out filePath, out tarEntryType) != null) + { + Console.WriteLine("Got {0}", filePath); + +// if (ArchiveConstants.CONTROL_FILE_PATH == filePath) +// { +// gotControlFile = true; +// } + + if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) + { +// string fileName = filePath.Remove(0, "Objects/".Length); +// +// if (fileName.StartsWith(part1.Name)) +// { + Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); + gotObject1File = true; +// } +// else if (fileName.StartsWith(part2.Name)) +// { +// Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); +// gotObject2File = true; +// } + } + else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + { + Assert.Fail("Found asset path in TestSaveItemToIarNoAssets()"); + } + } + // Assert.That(gotControlFile, Is.True, "No control file in archive"); Assert.That(gotObject1File, Is.True, "No item1 file in archive"); // Assert.That(gotObject2File, Is.True, "No object2 file in archive"); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 3d073bf51b..10a83ee826 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver public static int MAX_MAJOR_VERSION = 0; /// - /// Determine whether this oar will save assets. Default is true. + /// Determine whether this archive will save assets. Default is true. /// public bool SaveAssets { get; set; } From 91ec1a572ab82b67a3e3090bb9d90009c294ef99 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 26 May 2011 02:48:47 +0100 Subject: [PATCH 059/186] improve help information for "appearance show" at the moment, this just performs a baked avatar check for everybody in the region. If the check returns 'corrupt' then a baked texture is missing and other avatars will continue to see the gas ball. --- .../Avatar/Appearance/AppearanceInfoModule.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index 8589901947..7304145c1b 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs @@ -95,8 +95,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance scene.AddCommand( this, "appearance show", "appearance show", - "Show appearance information for each avatar in the simulator. At the moment, ", - ShowAppearanceInfo); + "Show appearance information for each avatar in the simulator.", + "At the moment this actually just checks that we have all the required baked textures. If not, then appearance is 'corrupt' and other avatars will continue to see a cloud.", + ShowAppearanceInfo); } protected void ShowAppearanceInfo(string module, string[] cmd) From 0c58a9e68074f3593920dc9f2356bbed96416497 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 26 May 2011 10:04:48 -0700 Subject: [PATCH 060/186] HG IM in grid mode working fairly well. Unknown target user references looked back in source user's User Agent service. --- .../InstantMessage/HGMessageTransferModule.cs | 74 +++++++++++++++++++ OpenSim/Server/Base/ServerUtils.cs | 4 + .../Hypergrid/UserAgentServerConnector.cs | 57 ++++++++++++-- .../Hypergrid/UserAgentServiceConnector.cs | 61 +++++++++++++++ .../InstantMessageServiceConnector.cs | 1 + .../HGInstantMessageService.cs | 22 ++++-- .../HypergridService/UserAgentService.cs | 24 ++++++ .../Services/Interfaces/IHypergridServices.cs | 3 + bin/Robust.HG.ini.example | 18 ++++- bin/config-include/GridCommon.ini.example | 6 ++ bin/config-include/GridHypergrid.ini | 11 +++ 11 files changed, 264 insertions(+), 17 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs index 9ba4e4953d..ed0211956c 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs @@ -194,6 +194,22 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage Util.FireAndForget(delegate { bool success = m_IMService.OutgoingInstantMessage(im, url); + if (!success && account == null) + { + // One last chance + string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID); + m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI); + if (recipientUUI != string.Empty) + { + UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty; + if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret)) + { + success = m_IMService.OutgoingInstantMessage(im, u); + if (success) + UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last); + } + } + } result(success); }); @@ -254,6 +270,64 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage result(false); } + private string TryGetRecipientUUI(UUID fromAgent, UUID toAgent) + { + // Let's call back the fromAgent's user agent service + // Maybe that service knows about the toAgent + IClientAPI client = LocateClientObject(fromAgent); + if (client != null) + { + AgentCircuitData circuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.AgentId); + if (circuit != null) + { + if (circuit.ServiceURLs.ContainsKey("HomeURI")) + { + string uasURL = circuit.ServiceURLs["HomeURI"].ToString(); + m_log.DebugFormat("[HG MESSAGE TRANSFER]: getting UUI of user {0} from {1}", toAgent, uasURL); + UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uasURL); + return uasConn.GetUUI(fromAgent, toAgent); + } + } + } + + return string.Empty; + } + + + /// + /// Find the scene for an agent + /// + private Scene GetClientScene(UUID agentId) + { + lock (m_Scenes) + { + foreach (Scene scene in m_Scenes) + { + ScenePresence presence = scene.GetScenePresence(agentId); + if (presence != null && !presence.IsChildAgent) + return scene; + } + } + + return null; + } + + /// + /// Find the client for a ID + /// + public IClientAPI LocateClientObject(UUID agentID) + { + Scene scene = GetClientScene(agentID); + if (scene != null) + { + ScenePresence presence = scene.GetScenePresence(agentID); + if (presence != null) + return presence.ControllingClient; + } + + return null; + } + #region IInstantMessageSimConnector public bool SendInstantMessage(GridInstantMessage im) { diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs index f4472c7dc0..6743a2e7c8 100644 --- a/OpenSim/Server/Base/ServerUtils.cs +++ b/OpenSim/Server/Base/ServerUtils.cs @@ -65,6 +65,10 @@ namespace OpenSim.Server.Base /// public static T LoadPlugin(string dllName, Object[] args) where T:class { + // This is good to debug configuration problems + //if (dllName == string.Empty) + // Util.PrintCallStack(); + string[] parts = dllName.Split(new char[] {':'}); dllName = parts[0]; diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index 942d96073b..eb184a57ba 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -54,6 +54,8 @@ namespace OpenSim.Server.Handlers.Hypergrid private IUserAgentService m_HomeUsersService; private string[] m_AuthorizedCallers; + private bool m_VerifyCallers = false; + public UserAgentServerConnector(IConfigSource config, IHttpServer server) : this(config, server, null) { @@ -76,6 +78,7 @@ namespace OpenSim.Server.Handlers.Hypergrid string loginServerIP = gridConfig.GetString("LoginServerIP", "127.0.0.1"); bool proxy = gridConfig.GetBoolean("HasProxy", false); + m_VerifyCallers = gridConfig.GetBoolean("VerifyCallers", false); string csv = gridConfig.GetString("AuthorizedCallers", "127.0.0.1"); csv = csv.Replace(" ", ""); m_AuthorizedCallers = csv.Split(','); @@ -91,6 +94,7 @@ namespace OpenSim.Server.Handlers.Hypergrid server.AddXmlRPCHandler("get_server_urls", GetServerURLs, false); server.AddXmlRPCHandler("locate_user", LocateUser, false); + server.AddXmlRPCHandler("get_uui", GetUUI, false); server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); } @@ -324,13 +328,17 @@ namespace OpenSim.Server.Handlers.Hypergrid { Hashtable hash = new Hashtable(); - bool authorized = false; - foreach (string s in m_AuthorizedCallers) - if (s == remoteClient.Address.ToString()) - { - authorized = true; - break; - } + bool authorized = true; + if (m_VerifyCallers) + { + authorized = false; + foreach (string s in m_AuthorizedCallers) + if (s == remoteClient.Address.ToString()) + { + authorized = true; + break; + } + } if (authorized) { @@ -354,5 +362,40 @@ namespace OpenSim.Server.Handlers.Hypergrid return response; } + + /// + /// Locates the user. + /// This is a sensitive operation, only authorized IP addresses can perform it. + /// + /// + /// + /// + public XmlRpcResponse GetUUI(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID") && requestData.ContainsKey("targetUserID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + string tuserID_str = (string)requestData["targetUserID"]; + UUID targetUserID = UUID.Zero; + UUID.TryParse(tuserID_str, out targetUserID); + string uui = m_HomeUsersService.GetUUI(userID, targetUserID); + if (uui != string.Empty) + hash["UUI"] = uui; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + } } diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 50036b36e8..1c01563014 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -576,6 +576,7 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { + m_log.DebugFormat("[XXX]: Calling locate_user on {0}", m_ServerURL); response = request.Send(m_ServerURL, 10000); } catch (Exception e) @@ -618,6 +619,66 @@ namespace OpenSim.Services.Connectors.Hypergrid return url; } + public string GetUUI(UUID userID, UUID targetUserID) + { + Hashtable hash = new Hashtable(); + 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; + + // Send and get reply + string uui = string.Empty; + XmlRpcResponse response = null; + try + { + m_log.DebugFormat("[XXX]: Calling get_uuid on {0}", m_ServerURL); + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return uui; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} 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 (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response."); + reason = "Exception: " + e.Message; + } + + return uui; + } + private bool GetBoolResponse(XmlRpcRequest request, out string reason) { //m_log.Debug("[USER AGENT CONNECTOR]: GetBoolResponse from/to " + m_ServerURL); diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs index 65ee7c7aeb..2a922de5a4 100644 --- a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs +++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs @@ -80,6 +80,7 @@ namespace OpenSim.Services.Connectors.InstantMessage } else { + m_log.DebugFormat("[GRID INSTANT MESSAGE]: No response from {0}", url); return false; } } diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index 6178ca1d7b..ca0fd7f350 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -64,8 +64,8 @@ namespace OpenSim.Services.HypergridService protected static IInstantMessageSimConnector m_IMSimConnector; - protected Dictionary m_UserLocationMap = new Dictionary(); - private ExpiringCache m_RegionCache; + protected static Dictionary m_UserLocationMap = new Dictionary(); + private static ExpiringCache m_RegionCache; public HGInstantMessageService(IConfigSource config) : this(config, null) @@ -155,6 +155,8 @@ namespace OpenSim.Services.HypergridService if (!firstTime) { lookupAgent = true; + upd = null; + url = string.Empty; } } else @@ -168,7 +170,6 @@ namespace OpenSim.Services.HypergridService // Are we needing to look-up an agent? if (lookupAgent) { - bool isPresent = false; // Non-cached user agent lookup. PresenceInfo[] presences = m_PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) @@ -177,17 +178,17 @@ namespace OpenSim.Services.HypergridService { if (p.RegionID != UUID.Zero) { + m_log.DebugFormat("[XXX]: Found presence in {0}", p.RegionID); upd = p; break; } - else - isPresent = true; } } - if (upd == null && isPresent) + if (upd == null) { // 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); } @@ -197,10 +198,10 @@ namespace OpenSim.Services.HypergridService // This is one way to end the recursive loop // if (!firstTime && ((previousLocation is PresenceInfo && upd != null && upd.RegionID == ((PresenceInfo)previousLocation).RegionID) || - (previousLocation is string && previousLocation.Equals(url)))) + (previousLocation is string && upd == null && previousLocation.Equals(url)))) { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); - m_log.DebugFormat("[XXX] Fail 1 {0} {1}", previousLocation, url); + m_log.DebugFormat("[HG IM SERVICE]: Fail 2 {0} {1}", previousLocation, url); return false; } @@ -242,9 +243,14 @@ namespace OpenSim.Services.HypergridService } if (reginfo != null) + { imresult = InstantMessageServiceConnector.SendInstantMessage(reginfo.ServerURI, im); + } else + { + m_log.DebugFormat("[HG IM SERVICE]: Failed to deliver message to {0}", reginfo.ServerURI); return false; + } if (imresult) { diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 59ad043cef..387547e252 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -485,6 +485,30 @@ namespace OpenSim.Services.HypergridService return string.Empty; } + + public string GetUUI(UUID userID, UUID targetUserID) + { + // Let's see if it's a local user + UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, targetUserID); + if (account != null) + return targetUserID.ToString() + ";" + m_GridName + ";" + account.FirstName + " " + account.LastName ; + + // Let's try the list of friends + FriendInfo[] friends = m_FriendsService.GetFriends(userID); + if (friends != null && friends.Length > 0) + { + foreach (FriendInfo f in friends) + if (f.Friend.StartsWith(targetUserID.ToString())) + { + // Let's remove the secret + UUID id; string tmp = string.Empty, secret = string.Empty; + if (Util.ParseUniversalUserIdentifier(f.Friend, out id, out tmp, out tmp, out tmp, out secret)) + return f.Friend.Replace(secret, "0"); + } + } + + return string.Empty; + } } class TravelingAgentInfo diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs index 3ab6d4f88b..753c20523c 100644 --- a/OpenSim/Services/Interfaces/IHypergridServices.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -57,6 +57,9 @@ namespace OpenSim.Services.Interfaces Dictionary GetServerURLs(UUID userID); string LocateUser(UUID userID); + // Tries to get the universal user identifier for the targetUserId + // on behalf of the userID + string GetUUI(UUID userID, UUID targetUserID); void StatusNotification(List friends, UUID userID, bool online); List GetOnlineFriends(UUID userID, List friends); diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 0d79e77b7a..bfefe32cff 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -21,7 +21,7 @@ ; * [[@]/][:] ; * [Startup] -ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector" +ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector" ; * This is common for all services, it's the network setup for the entire ; * server instance, if none is specified above @@ -316,7 +316,10 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" GridService = "OpenSim.Services.GridService.dll:GridService" GatekeeperService = "OpenSim.Services.HypergridService.dll:GatekeeperService" - + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService" + ; If you run this user agent server behind a proxy, set this to true ; HasProxy = false @@ -344,3 +347,14 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGAssetService" UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" ProfileServerURI = "http://127.0.0.1:8002/user" + +[HGFriendsService] + LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + +[HGInstantMessageService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.GridService.dll:GridService" + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index bc8bc0fdab..b2ecc79e8a 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -93,6 +93,12 @@ ;; uncomment the next line. You may want to do this on sims that have licensed content. ; OutboundPermission = False +[UserAgentService] + ; + ; === HG ONLY === + ; Change this to your user agent server + ; + UserAgentServerURI = "http://mygridserver.com:8002" [Modules] ;; Choose 0 or 1 cache modules, and the corresponding config file, if it exists. diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index 5142d90eda..d2cf89875a 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -24,12 +24,14 @@ EntityTransferModule = "HGEntityTransferModule" InventoryAccessModule = "HGInventoryAccessModule" LandServices = "RemoteLandServicesConnector" + FriendsModule = "HGFriendsModule" LandServiceInConnector = true NeighbourServiceInConnector = true SimulationServiceInConnector = true LibraryModule = true + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" @@ -63,3 +65,12 @@ [Friends] Connector = "OpenSim.Services.Connectors.dll:FriendsServicesConnector" + +[Messaging] + MessageTransferModule = HGMessageTransferModule + +[HGInstantMessageService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.Connectors.dll:GridServicesConnector" + PresenceService = "OpenSim.Services.Connectors.dll:PresenceServicesConnector" + UserAgentService = "OpenSim.Services.Connectors.dll:UserAgentServiceConnector" \ No newline at end of file From 0d29f7391629defa0ec1463fb24486ee76cca527 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 26 May 2011 19:13:03 -0700 Subject: [PATCH 061/186] Commented a few extra debug messages. --- .../Framework/UserManagement/UserManagementModule.cs | 4 ++-- .../Handlers/Hypergrid/HGFriendsServerPostHandler.cs | 5 +---- .../Connectors/Hypergrid/UserAgentServiceConnector.cs | 2 -- .../InstantMessage/InstantMessageServiceConnector.cs | 4 ++-- .../HypergridService/HGInstantMessageService.cs | 10 +++++----- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 4d073b2fe0..f721195ccf 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -143,7 +143,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) { - m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0}", uuid); + //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0}", uuid); if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) { remote_client.SendNameReply(uuid, "Mr", "OpenSim"); @@ -213,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public string GetUserName(UUID uuid) { - m_log.DebugFormat("[XXX] GetUserName {0}", uuid); + //m_log.DebugFormat("[XXX] GetUserName {0}", uuid); string[] names = GetUserNames(uuid); if (names.Length == 2) { diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs index 841811e843..5c89d0fd75 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs @@ -140,16 +140,13 @@ namespace OpenSim.Server.Handlers.Hypergrid byte[] NewFriendship(Dictionary request) { - m_log.DebugFormat("[XXX] 1"); if (!VerifyServiceKey(request)) return FailureResult(); - m_log.DebugFormat("[XXX] 2"); // OK, can proceed FriendInfo friend = new FriendInfo(request); UUID friendID; string tmp = string.Empty; - m_log.DebugFormat("[XXX] 3"); if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp)) return FailureResult(); @@ -221,7 +218,7 @@ namespace OpenSim.Server.Handlers.Hypergrid return false; } - m_log.DebugFormat("[XXX] Verification ok"); + m_log.DebugFormat("[HGFRIENDS HANDLER]: Verification ok"); return true; } diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 1c01563014..046f755f47 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -576,7 +576,6 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - m_log.DebugFormat("[XXX]: Calling locate_user on {0}", m_ServerURL); response = request.Send(m_ServerURL, 10000); } catch (Exception e) @@ -636,7 +635,6 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - m_log.DebugFormat("[XXX]: Calling get_uuid on {0}", m_ServerURL); response = request.Send(m_ServerURL, 10000); } catch (Exception e) diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs index 2a922de5a4..e94e3358e9 100644 --- a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs +++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs @@ -69,12 +69,12 @@ namespace OpenSim.Services.Connectors.InstantMessage { if ((string)responseData["success"] == "TRUE") { - m_log.DebugFormat("[XXX] Success"); + //m_log.DebugFormat("[XXX] Success"); return true; } else { - m_log.DebugFormat("[XXX] Fail"); + //m_log.DebugFormat("[XXX] Fail"); return false; } } diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index ca0fd7f350..dd5fd71baf 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -106,12 +106,12 @@ namespace OpenSim.Services.HypergridService public bool IncomingInstantMessage(GridInstantMessage im) { - m_log.DebugFormat("[HG IM SERVICE]: Received message {0} from {1} to {2}", im.message, im.fromAgentID, im.toAgentID); + m_log.DebugFormat("[HG IM SERVICE]: Received message from {0} to {1}", im.fromAgentID, im.toAgentID); UUID toAgentID = new UUID(im.toAgentID); if (m_IMSimConnector != null) { - m_log.DebugFormat("[XXX] SendIMToRegion local im connector"); + //m_log.DebugFormat("[XXX] SendIMToRegion local im connector"); return m_IMSimConnector.SendInstantMessage(im); } else @@ -120,7 +120,7 @@ namespace OpenSim.Services.HypergridService public bool OutgoingInstantMessage(GridInstantMessage im, string url) { - m_log.DebugFormat("[HG IM SERVICE]: Sending message {0} from {1} to {2}@{3}", im.message, im.fromAgentID, im.toAgentID, url); + m_log.DebugFormat("[HG IM SERVICE]: Sending message from {0} to {1}@{2}", im.fromAgentID, im.toAgentID, url); if (url != string.Empty) return TrySendInstantMessage(im, url, true); else @@ -165,7 +165,7 @@ namespace OpenSim.Services.HypergridService } } - m_log.DebugFormat("[XXX] Neeed lookup ? {0}", (lookupAgent ? "yes" : "no")); + //m_log.DebugFormat("[XXX] Neeed lookup ? {0}", (lookupAgent ? "yes" : "no")); // Are we needing to look-up an agent? if (lookupAgent) @@ -178,7 +178,7 @@ namespace OpenSim.Services.HypergridService { if (p.RegionID != UUID.Zero) { - m_log.DebugFormat("[XXX]: Found presence in {0}", p.RegionID); + //m_log.DebugFormat("[XXX]: Found presence in {0}", p.RegionID); upd = p; break; } From 07acb4d321d1388aeae7e789b59280dee8de63da Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 26 May 2011 19:15:39 -0700 Subject: [PATCH 062/186] Last commit before pushing. WARNING: (a) DB migration on the friends table; and (b) several config additions related to HG. See Robust.HG.ini.example, GridCommon.ini.example and/or StandaloneCommon.ini.example. --- bin/config-include/GridCommon.ini.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index b2ecc79e8a..486ba76a58 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -96,7 +96,7 @@ [UserAgentService] ; ; === HG ONLY === - ; Change this to your user agent server + ; Change this to your user agent server (HG robust) ; UserAgentServerURI = "http://mygridserver.com:8002" From abae859e7a7c21e855fdfe7ae454f35ead7a4480 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 26 May 2011 19:20:29 -0700 Subject: [PATCH 063/186] Added missing configuration variables to Robust.HG.ini.example --- bin/Robust.HG.ini.example | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index bfefe32cff..54f4650e89 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -216,6 +216,8 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 SRV_InventoryServerURI = "http://127.0.0.1:8002" SRV_AssetServerURI = "http://127.0.0.1:8002" SRV_ProfileServerURI = "http://127.0.0.1:8002/user" + SRV_FriendsServerURI = "http://127.0.0.1:8002/user" + SRV_IMServerURI = "http://127.0.0.1:8002/user" ;; Regular expressions for controlling which client versions are accepted/denied. ;; An empty string means nothing is checked. From 31d07859f9b073a8db080228192ce5303af54cd9 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 26 May 2011 19:43:24 -0700 Subject: [PATCH 064/186] Added missing config vars to StandaloneCommon.ini.example and fixed the ones in Robust.HG.ini.example --- bin/Robust.HG.ini.example | 4 ++-- bin/config-include/StandaloneCommon.ini.example | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 54f4650e89..0dd93f8bdb 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -216,8 +216,8 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 SRV_InventoryServerURI = "http://127.0.0.1:8002" SRV_AssetServerURI = "http://127.0.0.1:8002" SRV_ProfileServerURI = "http://127.0.0.1:8002/user" - SRV_FriendsServerURI = "http://127.0.0.1:8002/user" - SRV_IMServerURI = "http://127.0.0.1:8002/user" + SRV_FriendsServerURI = "http://127.0.0.1:8002" + SRV_IMServerURI = "http://127.0.0.1:8002" ;; Regular expressions for controlling which client versions are accepted/denied. ;; An empty string means nothing is checked. diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 67efa11564..df93cee589 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -82,6 +82,8 @@ SRV_InventoryServerURI = "http://127.0.0.1:9000" SRV_AssetServerURI = "http://127.0.0.1:9000" SRV_ProfileServerURI = "http://127.0.0.1:9000" + SRV_FriendsServerURI = "http://127.0.0.1:9000" + SRV_IMServerURI = "http://127.0.0.1:9000" ;; Regular expressions for controlling which client versions are accepted/denied. ;; An empty string means nothing is checked. From 36f9d55c363f0b6877a4eeb4a9d37ba989257393 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 27 May 2011 07:00:36 -0700 Subject: [PATCH 065/186] Added a BasicProfilemodule so that the profile-based actions (like give inventory, etc) work. This is just a mock profile, the same for all users, and with no DB backend behind it -- meaning that nothing will be saved. For serious profiles, use 3rd party implementations. --- .../Avatar/Profile/BasicProfileModule.cs | 173 ++++++++++++++++++ bin/config-include/Grid.ini | 3 + bin/config-include/GridHypergrid.ini | 2 + bin/config-include/Standalone.ini | 3 + bin/config-include/StandaloneHypergrid.ini | 3 + 5 files changed, 184 insertions(+) create mode 100644 OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs new file mode 100644 index 0000000000..e04fff6c78 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs @@ -0,0 +1,173 @@ +/* + * 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.Globalization; +using System.Reflection; + +using OpenMetaverse; +using log4net; +using Nini.Config; +using Mono.Addins; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Region.CoreModules.Avatar.Profile +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class BasicProfileModule : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + // + // Module vars + // + private List m_Scenes = new List(); + private bool m_Enabled = false; + + #region ISharedRegionModule + + public void Initialise(IConfigSource config) + { + if (config.Configs["Profiles"] != null) + { + if (config.Configs["Profiles"].GetString("Module", string.Empty) != "BasicProfileModule") + return; + } + + m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled"); + m_Enabled = true; + + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_Scenes) + { + if (!m_Scenes.Contains(scene)) + { + m_Scenes.Add(scene); + // Hook up events + scene.EventManager.OnNewClient += OnNewClient; + } + } + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_Scenes) + { + m_Scenes.Remove(scene); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "BasicProfileModule"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + #endregion + + /// New Client Event Handler + private void OnNewClient(IClientAPI client) + { + //Profile + client.OnRequestAvatarProperties += RequestAvatarProperties; + } + + public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID) + { + IScene s = remoteClient.Scene; + if (!(s is Scene)) + return; + + Scene scene = (Scene)s; + + string profileUrl = String.Empty; + string aboutText = String.Empty; + string firstLifeAboutText = String.Empty; + UUID image = UUID.Zero; + UUID firstLifeImage = UUID.Zero; + UUID partner = UUID.Zero; + uint wantMask = 0; + string wantText = String.Empty; + uint skillsMask = 0; + string skillsText = String.Empty; + string languages = String.Empty; + + Byte[] charterMember = Utils.StringToBytes("Avatar"); + + profileUrl = "No profile data"; + aboutText = string.Empty; + firstLifeAboutText = string.Empty; + image = UUID.Zero; + firstLifeImage = UUID.Zero; + partner = UUID.Zero; + + remoteClient.SendAvatarProperties(avatarID, aboutText, + Util.ToDateTime(0).ToString( + "M/d/yyyy", CultureInfo.InvariantCulture), + charterMember, firstLifeAboutText, + (uint)(0 & 0xff), + firstLifeImage, image, profileUrl, partner); + + //Viewer expects interest data when it asks for properties. + remoteClient.SendAvatarInterestsReply(avatarID, wantMask, wantText, + skillsMask, skillsText, languages); + } + + } +} \ No newline at end of file diff --git a/bin/config-include/Grid.ini b/bin/config-include/Grid.ini index ce5588eb1b..baadbb86ff 100644 --- a/bin/config-include/Grid.ini +++ b/bin/config-include/Grid.ini @@ -27,6 +27,9 @@ SimulationServiceInConnector = true LibraryModule = true +[Profiles] + Module = "BasicProfileModule" + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index d2cf89875a..72b74127d4 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -31,6 +31,8 @@ SimulationServiceInConnector = true LibraryModule = true +[Profiles] + Module = "BasicProfileModule" [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini index 6355d09041..cfcf5ed8c7 100644 --- a/bin/config-include/Standalone.ini +++ b/bin/config-include/Standalone.ini @@ -22,6 +22,9 @@ LLLoginServiceInConnector = true GridInfoServiceInConnector = true +[Profiles] + Module = "BasicProfileModule" + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index cd2d7a7bac..7d1ff60c2d 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -32,6 +32,9 @@ AuthenticationServiceInConnector = true SimulationServiceInConnector = true +[Profiles] + Module = "BasicProfileModule" + [Messaging] MessageTransferModule = HGMessageTransferModule From d60f525baa8697f896b9f756175118828db9ac78 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 27 May 2011 08:19:40 -0700 Subject: [PATCH 066/186] HG inventory transfers over the profile working. --- .../Inventory/HGInventoryBroker.cs | 17 ++++++++++++----- .../HypergridService/HGInventoryService.cs | 2 ++ .../InventoryService/XInventoryService.cs | 10 +++++----- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index eef60a10da..698fd569e4 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -217,12 +217,19 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return; } } - else - { - inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI"); - inventoryURL = inventoryURL.Trim(new char[] { '/' }); - } } + if (sp == null) + { + inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI"); + if (inventoryURL != null && inventoryURL != string.Empty) + { + inventoryURL = inventoryURL.Trim(new char[] { '/' }); + m_InventoryURLs.Add(userID, inventoryURL); + m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL); + } + + } + } } diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs index 9ee1ae4c5f..4eb61ba6b9 100644 --- a/OpenSim/Services/HypergridService/HGInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGInventoryService.cs @@ -134,6 +134,7 @@ namespace OpenSim.Services.HypergridService public override InventoryFolderBase GetRootFolder(UUID principalID) { + //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetRootFolder for {0}", principalID); // Warp! Root folder for travelers XInventoryFolder[] folders = m_Database.GetFolders( new string[] { "agentID", "folderName"}, @@ -171,6 +172,7 @@ namespace OpenSim.Services.HypergridService public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) { + //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type); return GetRootFolder(principalID); } diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 58c59ebb93..eeab67a666 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -40,9 +40,9 @@ namespace OpenSim.Services.InventoryService { public class XInventoryService : ServiceBase, IInventoryService { -// private static readonly ILog m_log = -// LogManager.GetLogger( -// MethodBase.GetCurrentMethod().DeclaringType); + //private static readonly ILog m_log = + // LogManager.GetLogger( + // MethodBase.GetCurrentMethod().DeclaringType); protected IXInventoryData m_Database; protected bool m_AllowDelete = true; @@ -385,8 +385,8 @@ namespace OpenSim.Services.InventoryService public virtual bool AddItem(InventoryItemBase item) { -// m_log.DebugFormat( -// "[XINVENTORY SERVICE]: Adding item {0} to folder {1} for {2}", item.ID, item.Folder, item.Owner); + //m_log.DebugFormat( + // "[XINVENTORY SERVICE]: Adding item {0} to folder {1} for {2}", item.ID, item.Folder, item.Owner); return m_Database.StoreItem(ConvertFromOpenSim(item)); } From 4087a453dc90356d8e62d371165b427096f5c26e Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 27 May 2011 08:53:26 -0700 Subject: [PATCH 067/186] Avoid a scary warning message about null replies from the user agent service. --- OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index eb184a57ba..9961164377 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -354,6 +354,8 @@ namespace OpenSim.Server.Handlers.Hypergrid string url = m_HomeUsersService.LocateUser(userID); if (url != string.Empty) hash["URL"] = url; + else + hash["result"] = "Unable to locate user"; } } @@ -389,6 +391,8 @@ namespace OpenSim.Server.Handlers.Hypergrid string uui = m_HomeUsersService.GetUUI(userID, targetUserID); if (uui != string.Empty) hash["UUI"] = uui; + else + hash["result"] = "User unknown"; } XmlRpcResponse response = new XmlRpcResponse(); From 0af5bb239f757eabfc4c59a18b88edfbf7afa6e6 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 27 May 2011 19:39:03 +0100 Subject: [PATCH 068/186] When saving an iar, don't chase down link asset IDs (since these points to other items rather than real assets) This bug had no practical effect other than to make "save iar" misreport the number of missing assets --- .../Inventory/Archiver/InventoryArchiveWriteRequest.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index b5272ad151..c34a0ecf90 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -157,7 +157,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService); m_archiveWriter.WriteFile(filename, serialization); - if (SaveAssets) + AssetType itemAssetType = (AssetType)inventoryItem.AssetType; + + // Don't chase down link asset items as they actually point to their target item IDs rather than an asset + if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); } From 4e4db749eb74bf02ae956c4a9461499988f0f0ec Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 27 May 2011 20:59:35 +0100 Subject: [PATCH 069/186] If parsing fails in the primitive base shape (which prints out a debug log message), also print out the name and uuid of the part containing this shape. This is to help in diagnosing parsing failures. --- .../Serialization/SceneObjectSerializer.cs | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 872816c450..47af0dd219 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -570,7 +570,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) { - obj.Shape = ReadShape(reader, "Shape"); + bool errors = false; + obj.Shape = ReadShape(reader, "Shape", out errors); + + if (errors) + m_log.DebugFormat( + "[SceneObjectSerializer]: Parsing PrimitiveBaseShape for object part {0} {1} encountered errors. Please see earlier log entries.", + obj.Name, obj.UUID); } private static void ProcessScale(SceneObjectPart obj, XmlTextReader reader) @@ -1470,7 +1476,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } catch (Exception e) { - m_log.DebugFormat("[SceneObjectSerializer]: exception while parsing {0}: {1}", nodeName, e); + m_log.DebugFormat( + "[SceneObjectSerializer]: exception while parsing {0} in object {1} {2}: {3}{4}", + obj.Name, obj.UUID, nodeName, e.Message, e.StackTrace); if (reader.NodeType == XmlNodeType.EndElement) reader.Read(); } @@ -1528,8 +1536,17 @@ namespace OpenSim.Region.Framework.Scenes.Serialization return tinv; } - static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name) + /// + /// Read a shape from xml input + /// + /// + /// The name of the xml element containing the shape + /// true if any errors were encountered during parsing, false otherwise + /// The shape parsed + static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors) { + errors = false; + PrimitiveBaseShape shape = new PrimitiveBaseShape(); if (reader.IsEmptyElement) @@ -1554,7 +1571,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } catch (Exception e) { - m_log.DebugFormat("[SceneObjectSerializer]: exception while parsing Shape {0}: {1}", nodeName, e); + errors = true; + m_log.DebugFormat( + "[SceneObjectSerializer]: exception while parsing Shape property {0}: {1}{2}", + nodeName, e.Message, e.StackTrace); + if (reader.NodeType == XmlNodeType.EndElement) reader.Read(); } From 76525be7b2cb1a72c45a72801dac871c4a338bcb Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 27 May 2011 13:07:18 -0700 Subject: [PATCH 070/186] HG lures working! Friends can offer friends HG teleports via the profile. WARNING: additional configuration for HG inis -- see *Common.ini.example --- .../InstantMessage/HGMessageTransferModule.cs | 1 - .../CoreModules/Avatar/Lure/HGLureModule.cs | 244 ++++++++++++++++++ .../CoreModules/Avatar/Lure/LureModule.cs | 15 +- .../EntityTransfer/EntityTransferModule.cs | 2 +- .../Interfaces/IEntityTransferModule.cs | 3 + .../InstantMessageServerConnector.cs | 45 +--- .../InstantMessageServiceConnector.cs | 1 + bin/config-include/GridCommon.ini.example | 6 + bin/config-include/GridHypergrid.ini | 3 +- .../StandaloneCommon.ini.example | 5 + bin/config-include/StandaloneHypergrid.ini | 3 +- 11 files changed, 280 insertions(+), 48 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs index ed0211956c..e0c404bba1 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs @@ -187,7 +187,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage // Is the user a local user? UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID); string url = string.Empty; - PresenceInfo upd; if (account == null) // foreign user url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI"); diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs new file mode 100644 index 0000000000..c82cfd2d75 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs @@ -0,0 +1,244 @@ +/* + * 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 Mono.Addins; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Connectors.Hypergrid; + +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.CoreModules.Avatar.Lure +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class HGLureModule : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private readonly List m_scenes = new List(); + + private IMessageTransferModule m_TransferModule = null; + private bool m_Enabled = false; + + private string m_ThisGridURL; + + private ExpiringCache m_PendingLures = new ExpiringCache(); + + public void Initialise(IConfigSource config) + { + if (config.Configs["Messaging"] != null) + { + if (config.Configs["Messaging"].GetString("LureModule", string.Empty) == "HGLureModule") + { + m_Enabled = true; + + m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", string.Empty); + m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name); + } + } + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_scenes) + { + m_scenes.Add(scene); + scene.EventManager.OnIncomingInstantMessage += OnIncomingInstantMessage; + scene.EventManager.OnNewClient += OnNewClient; + } + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + + if (m_TransferModule == null) + { + m_TransferModule = + scene.RequestModuleInterface(); + + if (m_TransferModule == null) + { + m_log.Error("[LURE MODULE]: No message transfer module, lures will not work!"); + + m_Enabled = false; + m_scenes.Clear(); + scene.EventManager.OnNewClient -= OnNewClient; + scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage; + } + } + + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_scenes) + { + m_scenes.Remove(scene); + scene.EventManager.OnNewClient -= OnNewClient; + scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage; + } + } + + void OnNewClient(IClientAPI client) + { + client.OnInstantMessage += OnInstantMessage; + client.OnStartLure += OnStartLure; + client.OnTeleportLureRequest += OnTeleportLureRequest; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "HGLureModule"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + void OnInstantMessage(IClientAPI client, GridInstantMessage im) + { + } + + void OnIncomingInstantMessage(GridInstantMessage im) + { + if (im.dialog == (byte)InstantMessageDialog.RequestTeleport) + { + UUID sessionID = new UUID(im.imSessionID); + m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message); + m_PendingLures.Add(sessionID, im, 7200); // 2 hours + + // Forward. We do this, because the IM module explicitly rejects + // IMs of this type + if (m_TransferModule != null) + m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); + + } + } + + public void OnStartLure(byte lureType, string message, UUID targetid, IClientAPI client) + { + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)(client.Scene); + ScenePresence presence = scene.GetScenePresence(client.AgentId); + + message += "@" + m_ThisGridURL; + + m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message); + + GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, + client.FirstName+" "+client.LastName, targetid, + (byte)InstantMessageDialog.RequestTeleport, false, + message, UUID.Random(), false, presence.AbsolutePosition, + new Byte[0]); + m.RegionID = client.Scene.RegionInfo.RegionID.Guid; + + if (m_TransferModule != null) + { + m_TransferModule.SendInstantMessage(m, + delegate(bool success) { }); + } + } + + public void OnTeleportLureRequest(UUID lureID, uint teleportFlags, IClientAPI client) + { + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)(client.Scene); + + GridInstantMessage im = null; + if (m_PendingLures.TryGetValue(lureID, out im)) + { + m_PendingLures.Remove(lureID); + Lure(client, teleportFlags, im); + } + else + m_log.DebugFormat("[HG LURE MODULE]: pending lure {0} not found", lureID); + + } + + private void Lure(IClientAPI client, uint teleportflags, GridInstantMessage im) + { + Scene scene = (Scene)(client.Scene); + GridRegion region = scene.GridService.GetRegionByUUID(scene.RegionInfo.ScopeID, new UUID(im.RegionID)); + if (region != null) + scene.RequestTeleportLocation(client, region.RegionHandle, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags); + else // we don't have that region here. Check if it's HG + { + string[] parts = im.message.Split(new char[] { '@' }); + if (parts.Length > 1) + { + string url = parts[parts.Length - 1]; // the last part + if (url.Trim(new char[] {'/'}) != m_ThisGridURL.Trim(new char[] {'/'})) + { + m_log.DebugFormat("[HG LURE MODULE]: Luring agent to grid {0} region {1} position {2}", url, im.RegionID, im.Position); + GatekeeperServiceConnector gConn = new GatekeeperServiceConnector(); + GridRegion gatekeeper = new GridRegion(); + gatekeeper.ServerURI = url; + GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(im.RegionID)); + if (finalDestination != null) + { + ScenePresence sp = scene.GetScenePresence(client.AgentId); + IEntityTransferModule transferMod = scene.RequestModuleInterface(); + IEventQueue eq = sp.Scene.RequestModuleInterface(); + if (transferMod != null && sp != null && eq != null) + transferMod.DoTeleport(sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags, eq); + } + } + } + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs index d1d7df2d9e..d295384279 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs @@ -45,16 +45,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure private readonly List m_scenes = new List(); private IMessageTransferModule m_TransferModule = null; - private bool m_Enabled = true; + private bool m_Enabled = false; public void Initialise(IConfigSource config) { if (config.Configs["Messaging"] != null) { if (config.Configs["Messaging"].GetString( - "LureModule", "LureModule") != + "LureModule", "LureModule") == "LureModule") - m_Enabled = false; + { + m_Enabled = true; + m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name); + } } } @@ -74,6 +77,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure public void RegionLoaded(Scene scene) { + if (!m_Enabled) + return; + if (m_TransferModule == null) { m_TransferModule = @@ -96,6 +102,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure public void RemoveRegion(Scene scene) { + if (!m_Enabled) + return; + lock (m_scenes) { m_scenes.Remove(scene); diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 6e4ec8175a..ec084fbaf2 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -248,7 +248,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } - protected void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq) + public void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq) { if (reg == null || finalDestination == null) { diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 8b96de46fd..07e97d5630 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -40,6 +40,9 @@ namespace OpenSim.Region.Framework.Interfaces void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); + void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, + Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); + void TeleportHome(UUID id, IClientAPI client); bool Cross(ScenePresence agent, bool isFlying); diff --git a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs index 138313aedd..74b742280f 100644 --- a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs @@ -125,7 +125,6 @@ namespace OpenSim.Server.Handlers.Hypergrid UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); UUID.TryParse((string)requestData["im_session_id"], out imSessionID); UUID.TryParse((string)requestData["region_id"], out RegionID); - try { timestamp = (uint)Convert.ToInt32((string)requestData["timestamp"]); @@ -185,45 +184,9 @@ namespace OpenSim.Server.Handlers.Hypergrid { } - try - { - pos_x = (uint)Convert.ToInt32((string)requestData["position_x"]); - } - catch (ArgumentException) - { - } - catch (FormatException) - { - } - catch (OverflowException) - { - } - try - { - pos_y = (uint)Convert.ToInt32((string)requestData["position_y"]); - } - catch (ArgumentException) - { - } - catch (FormatException) - { - } - catch (OverflowException) - { - } - try - { - pos_z = (uint)Convert.ToInt32((string)requestData["position_z"]); - } - catch (ArgumentException) - { - } - catch (FormatException) - { - } - catch (OverflowException) - { - } + float.TryParse((string)requestData["position_x"], out pos_x); + float.TryParse((string)requestData["position_y"], out pos_y); + float.TryParse((string)requestData["position_z"], out pos_z); Position = new Vector3(pos_x, pos_y, pos_z); @@ -243,7 +206,7 @@ namespace OpenSim.Server.Handlers.Hypergrid gim.fromAgentName = fromAgentName; gim.fromGroup = fromGroup; gim.imSessionID = imSessionID.Guid; - gim.RegionID = UUID.Zero.Guid; // RegionID.Guid; + gim.RegionID = RegionID.Guid; gim.timestamp = timestamp; gim.toAgentID = toAgentID.Guid; gim.message = message; diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs index e94e3358e9..161be02e26 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); + return gim; } diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index 486ba76a58..29f0de3af8 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -46,6 +46,12 @@ ;; Robust server in port 8002, but not always) Gatekeeper="http://mygridserver.com:8002" +[Messaging] + ;; change this to the address of your Gatekeeper service + ;; (usually bundled with the rest of the services in one + ;; Robust server in port 8002, but not always) + Gatekeeper = "http://mygridserver.com:8002" + [AvatarService] ; ; change this to your grid-wide grid server diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index 72b74127d4..510a315647 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -69,7 +69,8 @@ Connector = "OpenSim.Services.Connectors.dll:FriendsServicesConnector" [Messaging] - MessageTransferModule = HGMessageTransferModule + MessageTransferModule = HGMessageTransferModule + LureModule = HGLureModule [HGInstantMessageService] LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index df93cee589..931a77bb20 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -70,6 +70,11 @@ ;; change this to the address of your simulator Gatekeeper="http://127.0.0.1:9000" +[Messaging] + ; === HG ONLY === + ;; change this to the address of your simulator + Gatekeeper = "http://127.0.0.1:9000" + [LibraryModule] ; Set this if you want to change the name of the OpenSim Library ;LibraryName = "My World's Library" diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index 7d1ff60c2d..44ca3acaca 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -36,7 +36,8 @@ Module = "BasicProfileModule" [Messaging] - MessageTransferModule = HGMessageTransferModule + MessageTransferModule = HGMessageTransferModule + LureModule = HGLureModule [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" From e9988a3728706e346dfb869de554a24e6a3b0a79 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 27 May 2011 21:19:20 +0100 Subject: [PATCH 071/186] Make sure culture is en-US when saving archive related xml. This might resolve http://opensimulator.org/mantis/view.php?id=5475 --- OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs | 4 ++++ .../Framework/Scenes/Serialization/SceneObjectSerializer.cs | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index b88869882f..3078ab384e 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -230,6 +230,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// public void AssetRequestCallback(string id, object sender, AssetBase asset) { + Culture.SetCurrentCulture(); + try { lock (this) @@ -293,6 +295,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// protected void PerformAssetsRequestCallback(object o) { + Culture.SetCurrentCulture(); + try { m_assetsRequestCallback(m_foundAssetUuids, m_notFoundAssetUuids); diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 47af0dd219..6ae4f3856d 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -121,7 +121,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } } - /// /// Serialize a scene object to the original xml format /// From 44d5821c4ebac350a1db72abe7fa6c6527892f57 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 27 May 2011 13:35:22 -0700 Subject: [PATCH 072/186] Fixed one comment in a config file. --- bin/config-include/GridCommon.ini.example | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index 29f0de3af8..e022f1f205 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -47,6 +47,7 @@ Gatekeeper="http://mygridserver.com:8002" [Messaging] + ; === HG ONLY === ;; change this to the address of your Gatekeeper service ;; (usually bundled with the rest of the services in one ;; Robust server in port 8002, but not always) From 28cd03cda5c4beae2befeaef116b54dbd344c636 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 27 May 2011 22:54:03 +0100 Subject: [PATCH 073/186] fix bug where generic sqlite table delete wasn't working. this would have caused dupe links bugs when using the sqlite adaptor --- OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs index 3fb2d3facb..0d7ae1fc93 100644 --- a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs +++ b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs @@ -280,7 +280,7 @@ namespace OpenSim.Data.SQLite string where = String.Join(" and ", terms.ToArray()); - string query = String.Format("delete * from {0} where {1}", m_Realm, where); + string query = String.Format("delete from {0} where {1}", m_Realm, where); cmd.CommandText = query; From 6f4a2685cff4fd70658dda0a6c81c9b050541027 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 27 May 2011 23:43:31 +0100 Subject: [PATCH 074/186] minor: remove mono compiler warning --- OpenSim/Services/FreeswitchService/FreeswitchService.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Services/FreeswitchService/FreeswitchService.cs b/OpenSim/Services/FreeswitchService/FreeswitchService.cs index c3f10560d7..201e72f511 100644 --- a/OpenSim/Services/FreeswitchService/FreeswitchService.cs +++ b/OpenSim/Services/FreeswitchService/FreeswitchService.cs @@ -54,10 +54,10 @@ namespace OpenSim.Services.FreeswitchService Hashtable response = new Hashtable(); - foreach (DictionaryEntry item in request) - { -// m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value); - } +// foreach (DictionaryEntry item in request) +// { +//// m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value); +// } string requestcontext = (string) request["Hunt-Context"]; response["content_type"] = "text/xml"; From 99f42c0a6ec064d7b625c9b33e185a5e153d6be8 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Fri, 27 May 2011 19:05:16 -0400 Subject: [PATCH 075/186] Add option to disable logins This just covers script loading for now. More to come. --- OpenSim/Region/Framework/Scenes/Scene.cs | 18 ++++++++++++- .../RegionReadyModule/RegionReadyModule.cs | 25 ++++++++++++++++++- bin/OpenSimDefaults.ini | 1 + 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 4aae13c0ee..e9f5f9e28b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -94,7 +94,10 @@ namespace OpenSim.Region.Framework.Scenes // root agents when ACL denies access to root agent public bool m_strictAccessControl = true; public int MaxUndoCount = 5; + // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; + public bool LoginLock = false; public bool LoginsDisabled = true; + public bool StartDisabled = false; public bool LoadingPrims; public IXfer XferManager; @@ -1373,10 +1376,23 @@ namespace OpenSim.Region.Framework.Scenes IConfig startupConfig = m_config.Configs["Startup"]; if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) { + if (m_sceneGraph.GetActiveScriptsCount() == 0) + { + LoginLock = false; + } m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); - LoginsDisabled = false; + // For RegionReady lockouts + if( LoginLock == false) + { + LoginsDisabled = false; + } m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo); } + else + { + StartDisabled = true; + LoginsDisabled = true; + } } } catch (NotImplementedException) diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 122ad40719..c59c88c206 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -28,10 +28,13 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Net; +using System.IO; using log4net; using Nini.Config; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -50,6 +53,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady private bool m_lastOarLoadedOk; private int m_channelNotify = -1000; private bool m_enabled = false; + private bool m_disable_logins = false; Scene m_scene = null; @@ -68,10 +72,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady if (m_config != null) { m_enabled = m_config.GetBoolean("enabled", false); + if (m_enabled) { m_channelNotify = m_config.GetInt("channel_notify", m_channelNotify); - } + m_disable_logins = m_config.GetBoolean("login_disable", false); + } } // if (!m_enabled) @@ -93,6 +99,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName); + + if(m_disable_logins == true) + { + scene.LoginLock = true; + scene.LoginsDisabled = true; + m_log.InfoFormat("[RegionReady]: Logins disabled for {0}",m_scene.RegionInfo.RegionName); + } } public void RemoveRegion(Scene scene) @@ -148,6 +161,16 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady c.SenderUUID = UUID.Zero; c.Scene = m_scene; + if(m_disable_logins == true) + { + if(m_scene.StartDisabled == false) + { + m_scene.LoginsDisabled = false; + m_scene.LoginLock = false; + m_log.InfoFormat("[RegionReady]: Logins enabled for {0}", m_scene.RegionInfo.RegionName); + } + } + m_log.InfoFormat("[RegionReady]: Region \"{0}\" is ready: \"{1}\" on channel {2}", m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); m_scene.EventManager.TriggerOnChatBroadcast(this, c); diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index b32d198343..1d2420191f 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1174,6 +1174,7 @@ ; - the third field is a number indicating how many scripts failed to compile ; - "oar error" if supplied, provides the error message from the OAR load channel_notify = -800 + login_disable = false [MRM] From c7e18f9017302991f7a4411293ef2fbb20cc9b5a Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sat, 28 May 2011 11:11:01 -0400 Subject: [PATCH 076/186] Adding an event to signal that logins are enabled Added an event to signal the eabling of logins and added an alert to send to a configured service. --- .../Region/Framework/Scenes/EventManager.cs | 24 +++++ OpenSim/Region/Framework/Scenes/Scene.cs | 3 + .../RegionReadyModule/RegionReadyModule.cs | 87 ++++++++++++++++--- bin/OpenSimDefaults.ini | 3 + 4 files changed, 106 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index e04317b12b..b43d5f06ea 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -389,6 +389,9 @@ namespace OpenSim.Region.Framework.Scenes public delegate void RegionUp(GridRegion region); public event RegionUp OnRegionUp; + public delegate void LoginsEnabled(string regionName); + public event LoginsEnabled OnLoginsEnabled; + public class MoneyTransferArgs : EventArgs { public UUID sender; @@ -2218,5 +2221,26 @@ namespace OpenSim.Region.Framework.Scenes } } } + + public void TriggerLoginsEnabled (string regionName) + { + LoginsEnabled handler = OnLoginsEnabled; + + if ( handler != null) + { + foreach (LoginsEnabled d in handler.GetInvocationList()) + { + try + { + d(regionName); + } + catch (Exception e) + { + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for LoginsEnabled failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e9f5f9e28b..1d562fdb45 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1376,9 +1376,12 @@ namespace OpenSim.Region.Framework.Scenes IConfig startupConfig = m_config.Configs["Startup"]; if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) { + // This handles a case of a region having no scripts for the RegionReady module if (m_sceneGraph.GetActiveScriptsCount() == 0) { + // need to be able to tell these have changed in RegionReady LoginLock = false; + EventManager.TriggerLoginsEnabled(RegionInfo.RegionName); } m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); // For RegionReady lockouts diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index c59c88c206..eed64506ac 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.Reflection; using System.Net; using System.IO; +using System.Text; using log4net; using Nini.Config; @@ -54,6 +55,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady private int m_channelNotify = -1000; private bool m_enabled = false; private bool m_disable_logins = false; + private string m_uri = string.Empty; Scene m_scene = null; @@ -77,6 +79,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady { m_channelNotify = m_config.GetInt("channel_notify", m_channelNotify); m_disable_logins = m_config.GetBoolean("login_disable", false); + m_uri = m_config.GetString("alert_uri",string.Empty); } } @@ -97,6 +100,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; + m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName); @@ -105,6 +109,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady scene.LoginLock = true; scene.LoginsDisabled = true; m_log.InfoFormat("[RegionReady]: Logins disabled for {0}",m_scene.RegionInfo.RegionName); + + if(m_uri != string.Empty) + { + RRAlert("disabled"); + } } } @@ -161,19 +170,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady c.SenderUUID = UUID.Zero; c.Scene = m_scene; - if(m_disable_logins == true) - { - if(m_scene.StartDisabled == false) - { - m_scene.LoginsDisabled = false; - m_scene.LoginLock = false; - m_log.InfoFormat("[RegionReady]: Logins enabled for {0}", m_scene.RegionInfo.RegionName); - } - } - m_log.InfoFormat("[RegionReady]: Region \"{0}\" is ready: \"{1}\" on channel {2}", m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); - m_scene.EventManager.TriggerOnChatBroadcast(this, c); + + m_scene.EventManager.TriggerOnChatBroadcast(this, c); + m_scene.EventManager.TriggerLoginsEnabled(m_scene.RegionInfo.RegionName); } } @@ -188,5 +189,69 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_lastOarLoadedOk = false; } } + + void OnLoginsEnabled(string regionName) + { + if (m_disable_logins == true) + { + if (m_scene.StartDisabled == false) + { + m_scene.LoginsDisabled = false; + m_scene.LoginLock = false; + m_log.InfoFormat("[RegionReady]: Logins enabled for {0}", m_scene.RegionInfo.RegionName); + if ( m_uri != string.Empty ) + { + RRAlert("enabled"); + } + } + } + } + + public void RRAlert(string status) + { + string request_method = "POST"; + string content_type = "application/json"; + OSDMap RRAlert = new OSDMap(); + + RRAlert["alert"] = "region_ready"; + RRAlert["login"] = status; + RRAlert["region_name"] = m_scene.RegionInfo.RegionName; + RRAlert["region_id"] = m_scene.RegionInfo.RegionID; + + string strBuffer = ""; + byte[] buffer = new byte[1]; + try + { + strBuffer = OSDParser.SerializeJsonString(RRAlert); + Encoding str = Util.UTF8; + buffer = str.GetBytes(strBuffer); + + } + catch (Exception e) + { + m_log.WarnFormat("[RegionReady]: Exception thrown on alert: {0}", e.Message); + } + + WebRequest request = WebRequest.Create(m_uri); + request.Method = request_method; + request.ContentType = content_type; + + Stream os = null; + try + { + request.ContentLength = buffer.Length; + os = request.GetRequestStream(); + os.Write(buffer, 0, strBuffer.Length); + } + catch(Exception e) + { + m_log.WarnFormat("[RegionReady]: Exception thrown sending alert: {0}", e.Message); + } + finally + { + if (os != null) + os.Close(); + } + } } } diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 1d2420191f..8613d4ee72 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1174,7 +1174,10 @@ ; - the third field is a number indicating how many scripts failed to compile ; - "oar error" if supplied, provides the error message from the OAR load channel_notify = -800 + ; - disallow logins while scripts are loading login_disable = false + ; - send an alert as json to a service + alert_uri = "http://myappserver.net/my_handler/" [MRM] From 16fae059bbe09f26d9ef29156bddfcccf767269d Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sat, 28 May 2011 16:40:05 -0400 Subject: [PATCH 077/186] Comment the alert_uri so it remains disabled until set --- bin/OpenSimDefaults.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 8613d4ee72..fa5392dc42 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1177,7 +1177,7 @@ ; - disallow logins while scripts are loading login_disable = false ; - send an alert as json to a service - alert_uri = "http://myappserver.net/my_handler/" + ; alert_uri = "http://myappserver.net/my_handler/" [MRM] From d5326197ac530c955a585b2fac429a927b5baa42 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 28 May 2011 13:52:06 -0700 Subject: [PATCH 078/186] Fixed an issue with the response of CreateAgent over the SimulationConnector. --- .../Simulation/SimulationServiceConnector.cs | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index f38087383c..7cbd361f68 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -103,16 +103,31 @@ namespace OpenSim.Services.Connectors.Simulation args["teleport_flags"] = OSD.FromString(flags.ToString()); OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000); - if (result["Success"].AsBoolean()) - return true; - + bool success = result["success"].AsBoolean(); + if (success && result.ContainsKey("_Result")) + { + OSDMap data = (OSDMap)result["_Result"]; + + reason = data["reason"].AsString(); + success = data["success"].AsBoolean(); + return success; + } + + // Try the old version, uncompressed result = WebUtil.PostToService(uri, args, 30000); if (result["Success"].AsBoolean()) { - m_log.WarnFormat( - "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); - return true; + if (result.ContainsKey("_Result")) + { + OSDMap data = (OSDMap)result["_Result"]; + + reason = data["reason"].AsString(); + success = data["success"].AsBoolean(); + m_log.WarnFormat( + "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); + return success; + } } m_log.WarnFormat( From d671dbb7c743b2821cc36d845fc6ca94903625d9 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Sat, 28 May 2011 11:10:07 +0900 Subject: [PATCH 079/186] Removing mssql_connection.ini.example - mssql_connection.ini is no longer used --- bin/mssql_connection.ini.example | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 bin/mssql_connection.ini.example diff --git a/bin/mssql_connection.ini.example b/bin/mssql_connection.ini.example deleted file mode 100644 index e0ae7bace9..0000000000 --- a/bin/mssql_connection.ini.example +++ /dev/null @@ -1,18 +0,0 @@ -; The IniConfig.cs that parses this file by just finding the first key={value} in the whole text so comments aren't really honoured. -; Also, this algorithm can probably lead to 'amusing' results in unfortunate cases. - -[mssqlconnection] -data_source=\SQLEXPRESS -initial_catalog=database -persist_security_info=True -user_id=username -password=password - -; These entries are only for if you, for some reason, wish to customize your user server table names. -; Do note that if you change the table names, you might have to change the sql resources too manually -; If ommitted, default values will be used. - -userstablename=users -userfriendstablename=userfriends -agentstablename=agents -regionstablename=regions From 7ea6dfecd9ede7f5f8ad169d9e6777404d97b164 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Sat, 28 May 2011 12:07:23 +0900 Subject: [PATCH 080/186] Adding MSSQL connectionString example --- bin/config-include/GridCommon.ini.example | 8 ++++++++ bin/config-include/StandaloneCommon.ini.example | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index e022f1f205..c5c26ec8bd 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -14,6 +14,14 @@ ; Uncomment this line if you are using MySQL and want to use a different database for estates ;EstateConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;" + ; MSSQL + ; Uncomment these lines if you want to use MSSQL storage + ; Change the connection string to your db details + ; The value for server property is shown in your SQL Server Management Studio login dialog. + ; (This sample is the default of express edition) + ;StorageProvider = "OpenSim.Data.MSSQL.dll" + ;ConnectionString = "Server=localhost\SQLEXPRESS;Database=opensim;User Id=opensim; password=***;" + [AssetService] DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 931a77bb20..57380eefa4 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -16,6 +16,14 @@ ; Uncomment this line if you are using MySQL and want to use a different database for estates ;EstateConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;Old Guids=true;" + ; MSSQL + ; Uncomment these lines if you want to use MSSQL storage + ; Change the connection string to your db details + ; The value for server property is shown in your SQL Server Management Studio login dialog. + ; (This sample is the default of express edition) + ;StorageProvider = "OpenSim.Data.MSSQL.dll" + ;ConnectionString = "Server=localhost\SQLEXPRESS;Database=opensim;User Id=opensim; password=***;" + [AssetService] DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" AssetLoaderArgs = "assets/AssetSets.xml" From d473d9975e70366d0fd16276c9bafd5ec269dcd9 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 30 May 2011 17:15:55 -0700 Subject: [PATCH 081/186] Improved reuse on the WorldMap/WorldMapModule.cs --- .../World/WorldMap/WorldMapModule.cs | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 0cacf2dce1..10e1631a1a 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -233,20 +233,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } if (lookup) { - List mapBlocks = new List(); ; - - List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); - foreach (GridRegion r in regions) - { - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r); - mapBlocks.Add(block); - } - avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + List mapBlocks = GetAndSendBlocks(avatarPresence.ControllingClient, (int)(m_scene.RegionInfo.RegionLocX) - 4, (int)(m_scene.RegionInfo.RegionLocY) - 4, + (int)(m_scene.RegionInfo.RegionLocX) + 4, (int)(m_scene.RegionInfo.RegionLocY) + 4, 0); lock (cachedMapBlocks) cachedMapBlocks = mapBlocks; @@ -832,7 +820,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } } - protected virtual void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + protected virtual List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, @@ -847,6 +835,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap mapBlocks.Add(block); } remoteClient.SendMapBlock(mapBlocks, 0); + + return mapBlocks; } protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r) From e14b7ec9e115dd1705d6952f5ecbb19806709944 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 30 May 2011 17:19:46 -0700 Subject: [PATCH 082/186] HGWorldMap: don't send map blocks of hyperlinks that are farther than 4096 cells from the current region. --- .../CoreModules/Hypergrid/HGWorldMapModule.cs | 28 ++++++++++++++++--- .../Services/GridService/HypergridLinker.cs | 5 +++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs index 5ab334ffaf..0781de0485 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; using System.Reflection; using log4net; @@ -58,7 +59,7 @@ namespace OpenSim.Region.CoreModules.Hypergrid #endregion - protected override void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + protected override List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, @@ -67,9 +68,26 @@ namespace OpenSim.Region.CoreModules.Hypergrid foreach (GridRegion r in regions) { - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r); - mapBlocks.Add(block); + uint x = 0, y = 0; + long handle = 0; + if (r.RegionSecret != null && r.RegionSecret != string.Empty) + { + if (long.TryParse(r.RegionSecret, out handle)) + { + Utils.LongToUInts((ulong)handle, out x, out y); + x = x / Constants.RegionSize; + y = y / Constants.RegionSize; + } + } + + if (handle == 0 || + // Check the distance from the current region + (handle != 0 && Math.Abs((int)(x - m_scene.RegionInfo.RegionLocX)) < 4096 && Math.Abs((int)(y - m_scene.RegionInfo.RegionLocY)) < 4096)) + { + MapBlockData block = new MapBlockData(); + MapBlockFromGridRegion(block, r); + mapBlocks.Add(block); + } } // Different from super @@ -77,6 +95,8 @@ namespace OpenSim.Region.CoreModules.Hypergrid // remoteClient.SendMapBlock(mapBlocks, 0); + + return mapBlocks; } diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index c5390475f2..b7c0e91472 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -363,11 +363,14 @@ namespace OpenSim.Services.GridService else regInfo.RegionName = externalName; - m_log.Debug("[HYPERGRID LINKER]: naming linked region " + regInfo.RegionName); + m_log.DebugFormat("[HYPERGRID LINKER]: naming linked region {0}, handle {1}", regInfo.RegionName, handle.ToString()); // Get the map image regInfo.TerrainImage = m_GatekeeperConnector.GetMapImage(regionID, imageURL, m_MapTileDirectory); + // Store the origin's coordinates somewhere + regInfo.RegionSecret = handle.ToString(); + AddHyperlinkRegion(regInfo, handle); m_log.InfoFormat("[HYPERGRID LINKER]: Successfully linked to region {0} with image {1}", regInfo.RegionName, regInfo.TerrainImage); return true; From b81a304baaeeee4e0dabb42c8e217c3c30be9863 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 30 May 2011 20:12:05 -0700 Subject: [PATCH 083/186] Made the GatekeeperConnector a public property. --- OpenSim/Services/GridService/HypergridLinker.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index b7c0e91472..64935af387 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -61,6 +61,10 @@ namespace OpenSim.Services.GridService protected GridService m_GridService; protected IAssetService m_AssetService; protected GatekeeperServiceConnector m_GatekeeperConnector; + public GatekeeperServiceConnector GatekeeperConnector + { + get { return m_GatekeeperConnector; } + } protected UUID m_ScopeID = UUID.Zero; protected bool m_Check4096 = true; From 44371118a2ac50b21e31995d3bcc309a5e1dc56c Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 30 May 2011 20:23:45 -0700 Subject: [PATCH 084/186] Made GetMapImage public in the Hyperlinker --- OpenSim/Services/GridService/HypergridLinker.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index 64935af387..52625980cc 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -61,10 +61,6 @@ namespace OpenSim.Services.GridService protected GridService m_GridService; protected IAssetService m_AssetService; protected GatekeeperServiceConnector m_GatekeeperConnector; - public GatekeeperServiceConnector GatekeeperConnector - { - get { return m_GatekeeperConnector; } - } protected UUID m_ScopeID = UUID.Zero; protected bool m_Check4096 = true; @@ -370,7 +366,7 @@ namespace OpenSim.Services.GridService m_log.DebugFormat("[HYPERGRID LINKER]: naming linked region {0}, handle {1}", regInfo.RegionName, handle.ToString()); // Get the map image - regInfo.TerrainImage = m_GatekeeperConnector.GetMapImage(regionID, imageURL, m_MapTileDirectory); + regInfo.TerrainImage = GetMapImage(regionID, imageURL); // Store the origin's coordinates somewhere regInfo.RegionSecret = handle.ToString(); @@ -470,6 +466,10 @@ namespace OpenSim.Services.GridService m_Database.Delete(regionID); } + public UUID GetMapImage(UUID regionID, string imageURL) + { + return m_GatekeeperConnector.GetMapImage(regionID, imageURL, m_MapTileDirectory); + } #endregion From c4b265aeae712432bebaca1aa3c97bbafe14e3e2 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 31 May 2011 18:47:13 +0100 Subject: [PATCH 085/186] update libomv libraries to 0.9.0 this is a prerequisite to fixing llDialog issues for the latest Linden viewers, since they are now making use of a new OwnerData field in the ScriptDialog message --- .../Avatar/XmlRpcGroups/GroupsModule.cs | 27 ++++++++++++++---- bin/OpenMetaverse.Rendering.Meshmerizer.dll | Bin 20480 -> 20480 bytes bin/OpenMetaverse.StructuredData.dll | Bin 102400 -> 102400 bytes bin/OpenMetaverse.dll | Bin 1716224 -> 1736704 bytes bin/OpenMetaverseTypes.dll | Bin 114688 -> 114688 bytes 5 files changed, 22 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 1c791b9d36..05223e067c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1231,20 +1231,36 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId, dataForAgentID); GroupMembershipData[] membershipArray; - if (requestingClient.AgentId != dataForAgentID) - { + // c_scene and property accessor 'is_god' are in support of the opertions to bypass 'hidden' group attributes for + // those with a GodLike aspect. + Scene c_scene = (Scene) requestingClient.Scene; + bool is_god = c_scene.Permissions.IsGod(requestingClient.AgentId); + + if(is_god) { Predicate showInProfile = delegate(GroupMembershipData membership) { return membership.ListInProfile; }; - membershipArray = membershipData.FindAll(showInProfile).ToArray(); + membershipArray = membershipData.ToArray(); } else { - membershipArray = membershipData.ToArray(); - } + if (requestingClient.AgentId != dataForAgentID) + { + Predicate showInProfile = delegate(GroupMembershipData membership) + { + return membership.ListInProfile; + }; + + membershipArray = membershipData.FindAll(showInProfile).ToArray(); + } + else + { + membershipArray = membershipData.ToArray(); + } + } if (m_debugEnabled) { m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); @@ -1257,6 +1273,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return membershipArray; } + private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); diff --git a/bin/OpenMetaverse.Rendering.Meshmerizer.dll b/bin/OpenMetaverse.Rendering.Meshmerizer.dll index 6139a9d5d94158f6eb12cc1e0c4c757d86ce7c99..a6dec044616d76c608b2656c94d6a4f98783f125 100755 GIT binary patch delta 51 zcmV-30L=e@paFoO0g#9UbLG=bv5ZnA1_=NF0KapyWaY6^nnzg5WHueOmurUC^O6JW^R9x5vZax!=+G$qp)2+lH|EsQe%VrCm G6UqSheiN7g diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll index e3b729c6ee2bcf7b067665142f5155b0e84d2bc2..ed0a2d6446f811c578cf2c727fabe8867e500654 100755 GIT binary patch literal 102400 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 CdRBV? diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll index 69c4e9b9dff447e4e86c42c36594252ed1d5b97a..37ec47a7a8fc3a35b657b4b3cee2cad0cb14da5a 100755 GIT binary patch literal 1736704 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

q+kS%6kM%La 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

f) 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 z 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 ?lEGCi!|A6$`Y}(wTpEnO`AB$ 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 O&r9HW3H<+C0{<5k{3Txi diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll index cab014d534e23b4f7c048e461a4cd5513ae3cc48..6f7fbacb5abb14b47a1de156670ccac964cda8d4 100755 GIT binary patch literal 114688 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�#XBdVtAXuwHTX_Pv#iZz~8 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񪔎xaUK)0Yt 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

_%`b;xOIi!`z8BPm$mdoka zr^}Vw+UHr;4n`Jw3GG?d4&gM^r^}VgDdhrt8oL-d%Xyk|rXBpWGC9L(JpZxPm2lPl zF!qk4%VL!?I6EGUX_-x>A~O~YgN4O&1t#jj53SA|_#~S4{Gc1K27C-nJB%J`k(X8Q zKslaE;A}A+!y8sPyuO<)hDCxIr~v|MXYS(L>YosOB6QF-LX-X{3G^2|S9m{zVtB5_ z6MDX1x#Y1!xC%wXU@Mz3kz91G~ zzJPbGY&FS(Qm_MF*^_;&CCBMv3Ov}u@gAQ@jl zFP%)AfYhsn${KcycgcyttgoY*aGT9N9~Jrpw%$yB8dvc=jQ1qgfr9p=xzIV7?w_D{ z>Lc|2-OLd>Yrh`pT83PrE09ThA|)kN%cPr9>y`)gt4N)d6xmppu4?A#VNpmo9c`c} zJQ**m9UfxN#i_?`{z*D>(S>xqaO9FWB_Z=9Q=Zl`OBm0lK~TLI#IzE63mKO<;2hkq zzPvt=bwg>XaQ5w6qhvW8iRP}%ID zO6$u6FI0|IpfbqGOfOWL7*w&eO!-3P1OzIBoXq_~%SR{u223Z?F+5O!FXcw#-K#^^h?qyVSJa5faJlB zZvgTkKi><{Rwb2j5=*bE!HI`qG@&*j4wS|-mZUgXI%&L58o@V_*yt+bNAMROy_uks ze#BA01fBFJ4g)6WtVG1*XEw~xr3@UFFx->~%*e-G0ZX03EfL5XHU_~k)j1NTQ6aXP z6HnyeWb2Sq>p4fJc)t}S3mg{?W*m_ezd3X&mIO%U=n>|daLJdWhtC(!(sDyJO;86? zIaY-7gD=O4FyFZF4P0}mc1r4YN=~Rv>2^wOp`C2?A(T0QzHEEruu+xU1F5L%MSY|K z=MF?LV}Y?%jjb_`-bgchP>#1+e&0qY#gW6<2c-nlc0nn@2D>Xtahx&sKq)eLv%x(@y?I{S}9E*LL>ct&en8tLtgLe0~xli4C=#Z zSaNGMgi`U48>{~vo#OwdeV}J~<7hh$c0^4tbxU6#ZHK`wsPlj1cKSYiZ=TG%7_36Q zOtaf|Uqk6o|I($mT`82_LeKiBYOz0+bV6x3&AO2DZo5Xh?A9GlOSkQf8ZoExf7P#(n$WLPe*B%F))&#B> zmcZHZfb0GToTdY=XKUaz8gK?uAI$}vf#B?hz!?b6jtD&HkL-%TbμuEl|yB{}R8 z#qHD3_(?;ctt2q_%y14@ZXcwJV`^*hvohuOLb|x9ww|Py*$?ToAEaR*>1FmrI_-&c z29jQ8U!;ozn=5*(zs%l97gyHSm-1!yN4hw*ZVgEJ1FMUbhag^IJS!o_L3 zaB=DqF3ws)#o3hM;xuizI8_Z7r%<8dZ0T@uT0UHymJnQAQ1=8D7mo|+E*=)rT|6qJ zyD9GLZi)xGo8p1)rg)&cDemiTiU+!z;(_j_c%Zu}?(1%f2fCZ$f$pYwpu4z#Nq0&K zry)}@jd*uRck$+s?xwh}yD1*%Zi)xGo8p1)rns-WDIVxa0Y_Y zD!>^CPOAWCAUMqdoPoB7rT&QVu*@Fa<>u%vw}!tH#JE8#beG%0-#?jArMuh`-Q|Yp zF1JIlLe-N`utL>yjlV(#XKLSFZUcXBk5ua3U2cKyaszaS^v63A1N{LmPk-=Ff54LN z04jrgxivtgZ}`WN$V;Pu${=5E8&K&d{xK!;(oH~R;GYSBN@oF;LB8Bzpwe^l<#q#= z{*y2FB2ei?{uw6tn$dv)F0}xPN6?ta%OGEFQ&8zw`Eu_9l@`vITNqUOSiaoQpwiRw zA$vzvrLEK`L`YMMPgxGknX65W z;||wk*PO|X`Sn{M^fR3IqH*Y3Jak2r4kc%~!KftJ+#nk?@w1gq$3c;7$sk**l&u2m zw6Za*+%vTZbVDNoeJ^yJ4Bqry-0Vk8vS|?{8$}>Zyh*Z&2$D^UAlWDaBa)3?T<*kL z1bVCyfetDn1Y;v3S_H|aMUZS1As8|xn}{IUv=-fsGdbEfT46lr6 z5hR-yL9$T<(nLMUCL%~SErMjD2#iQJ_Kl!xV83FiHwTWzrJ56%P=XA z<8mCo6yjC{FMoOcpqpgxVwt#Wr@Hd(<3nZM-dx9LQ1}YeZuqXpbe!P&51ik75>Mk- zct6LJ6@1&tI}2qi@xw5zXGQ07?@I{fvmYbyb*FkfU>-633CCLlDjwTYprwcoCD56m zn`AA}e9u~GBZ42NclmL8j31|8`*HfJAE*EMar%@Wr|0`|I-MV8ui>ki2HJd1w1Z?2W&MmSY8Sc86?ZLmgtmB?Tt^b>xA;g<@i zs=@Ffe=2LR(U#2M2E(rlP+@~L;Un}RvVr}HX1WBv{H<)q>UZ!bgMV8<`9>&R#Q$SOZ_njiTzBk&R0 z7?ZGk>&Z?!dqwFt_}7eoyW!uF_}BUw|9%B6>|Ye1yoC{B73AQU`vJm{=wrUD@DP4SLKW~2ZmnkF0xh0+ zTfO&zt&GP+aE;u*_-FM#K!ja@DR_5F560P`5PLyTNOVFzDMZ%@3Q@ySA<@yViGIO+ zQb;uRYobq-3W@4|Av#1*h&>{xiO!G>nSyq}tGep&0e09Ms(&8;zE3+i$Pi7rL4zhh ztj523{NwLcaA-iwu|*Nk90=H^+2Z`b=+TP!78%e?C_)1vplJ|@QNj!=6I*0Jlc5NW zg@9&4AO;FE;FYQ^vY-J`h^9k8qao1dDk%}-rhRC)A#67fX89ui(S2s|azNO2Nf7bU zfP5IPwHe=d(Z-9(44(zA%@>ndeM|Nm#6%k~CeuBcXcNX{iZ5dlvf&^mw~Ed&nfu8^ zn=vNyeHoK7I}T!_4H=U~5!q-{#$>${W>aQMdum!Og<1G_`aKXtPxa%tj0TXmg$IC- zlOV?d{rFIq{@M;ZHomsQE)7B1#rU-y_T%i=dE@shxOUwqnSfkPM6yP8)|k#&`Yw;3 z^EoikIZ^C~M1-~Bd>ZaKOHNzov307gxj|LV|5FfFqECi@kDGGwJ33^>@90pLxM3Cb z)^YfhAJiuEKx!GTL~6()gNVoiM20KTb+L8w2#j=Va4{w7-3&hFG8cYgX+VN}&4zis zdywr6#`Jx@(UA8D$}0tI@7qY`H+a5^F!%JZg0zM4shl`6i8Kd@ z407U-BvMuo8RW!;Nu+5&WRTO{LG*Ui%Ak%gH_UTn>cL@o-6zD-%z%DMh%Zuz`6)EM z5f~}rO5~>33V0WwtRGO{sOm4t5-QENdBZ4o$|1#>97bhp9uk=8VN}vXVlzFA;$3*& z+g}jKQfB+Ep={qZl`q$_#0A~zafSBlT_lrML#KTLDNUe+tKvV z^42tc)Nj*&_%4ByWs$ZZtU7^@*ADIO@5%v*)91cGi&LVy7adf zE;T+Hn!NCd1$hts0P$OYF4OKyskX^qeZ`QORhC{y*Lum4#0aV5(k|web(Vm`^Lqsg zhV-8(UwIucas@Quq{qU5CdSoMwx(@E8|TZK#I$j~tYJ(W=gXSMv~fPvZymL+qz4y8 z$ODR;UvgOllq*p5Q+;yGQ%aMKn*w%klZ{J!$;NedC>vM3p=?~gN;WPYL)o~g2xa3I zL9%h3o-5hJk@GZ)jGCWCT1Z|l&Pwv?3r@gq^;z9XR;6OT{HBN0~mRHeVl8 z%;*yoyWKD5>t~Aj`k7)zzo6J1ez8IN^4XTr*Nm%v`a>kr~oK=`pG=0W% zFm!Rb&OQez#kZ9IVFfuxBSUlAgkv=FG#HN2$kkw2%agCcKK^$cO4ac@4yEecvg-I9 zhf;OsI}UQbIhUOVe{lS;DW{b>g4l8_a5Be0!Jq@*{~BaXehq@n!m~8+-s0T*Us@ku zWkl>YqA{d_8B&#QzdLMAmjB`$u|<8$mj2x{QP)p4YcuA z+T{Q7b#pA3e^2KgeRCbhfN|z*M9x7BkT&ms7&9E5!pe~c~Bg#z0A&e9{uRO8dPh?5? zSr`9z4k*O-7=x@{7H?~`yk8^a2l9KF*ZU2CW~tBVCL%x2dac#0b#tZ`sQg@_96y9` z{$>j*;T^)$P-X_p^o%06-vOBD?Q@6n|8P5w+3P&m-jDb+zbFwr~-aL1+RVpky1_p&q|W@ zsZBU#VZGigfQ|f-Tm2o7X=%lK?d_#uYy*t^0xp{*w~zv2x`|t;0MgyZ_k>WhEo zBM-=xTorZ`{5rC)$B`G7Y_{sZVY9YLTGX)gT2P--NvYwv)$rv3-dnQo&MQiC@i|`Z zKep#ye*GWao>Auv8nhl3EteRx9~1baAdu0w=@I9YWWW5sVpGU2W4rMWYEW)dp_Kd} ztg0SN|DC-To?DXn4#@nUkMk4%oy_6~t^d90Ah7?+YfHLZ^M6~Hk2h@uvLADCNp>{3 z%ERw%d^Idvg^pZ>c3&0EOsOu;1X`R=+Az}WLN$W=Y1PFwOpwfJ$!r&D5KgZyu4e*^ z^+~$>4R8J!^nL)HL0`bB~0Q?qkTTRRxg=j^*fUhPd9d8U^Ta#O8 zLKrVJ170BOGkjGtiM-bOqgCK$2k{Wm{O+qo~W-oY^6$tK3+`#0s)1!nlq_qJ^)} z?YP>v-L-1JxBYmldhYMqj+Pp({^&$x-L%f?nTV?TJOHyK?7`;)lYLnddRiH61IXSw zIHTRu9^|xp@bunf<-C6;8xMb0FF6;c09d``X&3P2KQ5Ge$u?TRmui#k(~HBZODn~{bxowO16Z}4tQi+(0jX@Ahr40;oMy73#`1PT zh;L>@-3xX_dvDGV7ItQt?R+DIBtwB+kXE34m{402;Iu2^?RUUu?9G{-%Y3F}4q3-Y zADg5W_WQn3sm==)vlyQ#?1kt6kMY~KVZ3fztn)wGN)|+xuWt-WGLIo2G#%R(}&#$B&(C z$?E9gbsQfOS=kF4`;XhLWQVy2mh8|Cd5(oVJ%>=)GHVQ!s=-K=vfYA6<>L2052bC4 zU~g<)Fzw4C&p0(1Xr`OrhIh8l+pKFzCpr zq9v+yfXbMGeO?lI#8+N~T$n0LzTy-PMsm;LV1W4`X!Tkbd|erID{YLK9CZ!fI8Yf= z=aH|ghg0%(!^3H4FyZZ2T)ddrmkRET8PArni>1s?l@Gi5RSn=ETs6}w>C6F(oe%b(r>~) zSwtZu{hRoAIQ|WX{blk;ob)vRfrj->K<~umpl5N6h6AzZ7{v7NkOX8~lWk2tFSw*6 zWpHB3$80)FRA;%9Sx`ZAx#kNDbpsRjz-+;O2uL0I?4$)D=eQ(i=@OCTWjlrL426EH zDgwK5FyNgbo`LbtDB6a861p=a`ueos&X6c>sQ#THt@Eg@T@I2vDZA_HC=y_T+E4FcaSz5>!8RmEQ_5tXMCT1=T`HvXPFZm@KH~*_qeX@j_A9<W#M$LVpEwoM7P;JvSRNHiw+J?S|z0sh% zK@=DFCA9jwwSkJTrk#OOHY@v7xsn5P9H^7%5aVxu3}LU}9#64E-?-QT`pB9WcT4&&IFc`I2mt|FmxB|2Tw}T4pIDf{tr>Q7@n4dG>tzsJQ-SK-H+^#^9~ zQWB>!+?-|5S>eR-<5v&DQ7T=TH1V4;<584GjZh8SB|$7n3X!UZr; zCYSp^e8sVH56x@9SRC9>3iW`1Mz+S`%$+6a16%dse3>5_AI_I~qhXmZ`55KHeH8gC zbS*B)iPe*!+erGvkmEc~EX{_6& zxRwvEigD$oubwbw-$>|c__nz_lEB@O z#?mWTOyB)34e>gykUU4-%4NVLu4FYi2TVZQj7 zeQk^U%I6T%cgtrI(|1Gj$w!)h(AFH!u|byKUAbvnb+|lVOgH(3VJTgTGe7GO`18eelV2E?(xo`_8~LPs9v`=K zx=p4|{xBO0e{n6`g%vYt?#v_{ z@?=5z!JXn-^1fd^J2&jS6~Fo4S~K!>M1EWidksCOLrir#ca!?}MlscvU4`Ln)Bik@ z{RID>izK|D6Uwf*NW%J1f=QL}u>VCQ@K*x*c(WDzb8fXuxUKP(!H!&Vu|>Eem%Lmz zkA}?Hmtp^kQ&K2&I27Xkb$f)t{&gjOkqD)N-6%^3yHWOm@H;d!GzY8%7}I-OJvJ^v zU8OziE@SjB8gt7!Mt-V!;Epxesfy_SPE|w?Hm8zQ+MEV@@hpRNnM%m21L7E8it)EP zN|1vDlDs{U?F`2F zx;K8Y6-C(*5a1VEiGWBcOoQPUTY*^FU!!w}@?sxJ%-?&43Lr(4kR4_#Dx+tV3CBJa zRdb9T%K38B7OF<}d?Dsc4x`u)4b%c3(;ln^zUVDlpicUphYQO`zO9dKLXB=V2SYX_ekM{HpsaJ^XCkE;*q@H3sqiN& zBgy-3-b^U9sLAawpp8Uk0quV`-ERceb)c^5-`BNmbr>zM%;vbHm)VTjH_C{0Fb5GV zvxVddw%A%tq0KUzqWMc}^zRt&Du&k9kK&PSLuqZzf~B=J%a*OCS$-ds-|AZWg@C23 zrAsWimM*b0tLKZ#ySuEGnaOlVSuI~RAkT2q(}Fx)M%ND-?Y25*W7slWx6pkDj-6X| zvVob)$Bd6Uv<&37)nWVNjM-eb?Q8t>bWV_)>*zrK5(vL8$bQy;4N`m>ZfXeaT21rU zJVN^#XxSEPb8T-P&qA^zJk0T}*-NZ7T|nE@!#6ueBGPjdKtD-B_l`!)&wIJG<`|%o zcM&2wFG)hTyF3j*=b9JuNDd9`RM8s=D)T3qL+&&FI)G*TlOydycFI4UuRdYUw(h`#(&&= z|Mn}cyl0PBo_X}OIqyGq`_ETwn11S!Z|wD>%2zh#cYWcu+o!(TvXk0$NdF-}{(k1z z=bya)&-aZT|Ma~JzI@puKN@!9;}2c)kmbeCjU98(s}=lAeEj?zYj# zerwnEr4L-Z`^M9plV6KG*1Z18Z1v0Ue&Ou9Pj0&Z0q4fIp1ii>rH9^L_l*0Q8SkrM z7u}q=yy42KpFLW6;_2Ms1kdefEKB@gIM8nX{tz z#>mKT{W*T-!l#G*<-4!m)qU_g57zwpp(oB?eeS~_yfOOq#rw7Yr0!3vU%a4u{!9PN z9ed9KKRo3Aola4YUH|6PM_=0g#y95u__7VVp7it!H~jO@ue^BTJ15Nj;MJ8g_C9yn z9nU|s=qEkx(LH}L+U_`Je)865R#(2h%gM2WZ{6LRSY4fZ;+*D+XC~Z#{K9+BE;J`z zTKe#{Zyo!?s`ob?edRN+P8xUR^LO2M^N+t*zw5pEGb-OSKpR(gVFaP=*pI-mfx|Y|XXJt0_)TEaD{Bt`W_odxVJgM^L&J$Oq zepL0=S3gW#I`K}Gy!#rrZ_i7Iy|@1Q_~(!RV`R+cr<@axTDbUcKUmh?fAY)~jlXi1 zuRLw!OPhb%`r;QlSN){=*?F%oE4=aW`|rQ|#6@$Tc(DHEi|$(V_Vus4vgXnku6z2a z4YLmY;~NM4VcDZEEL-^4*I#$;pS}Ogd-nZFYvqRdBa`3w>pXkrqE*q|zy0o_H;#B? z+0E}>v~t>KpEzOf3+_Gk2P4i}`q4Hzvq(9`&y$X-h1RtAO85MX+L`Y{`0SSwQcmBo4W3L>bS48{Bg-|ufG1oQNjUEbBnbLRqV`pPhK{B)kAOI*?M>HtdS2?eC49`msCFS@-H5IcjM}@ zZ@iXzY5j}m?D6JHfB5^ouOGkite-SJmwDohu9k=Y`m;~pRrvHi4>tU=Gk)%;P8{~( z|Lp86Ju($Ze|Syz7f-lz@!wzkaQU%&{b)tzGjArp_WSjfKR*1d=z&k&Ywvh$%d(sP zmRa=t0sEY=-)o;(}46U2Nv_k6h~f__;|7Hy!@uvRB7XUbXbzhvpsov^Dbh zqrTKy$nNk&>b~nPs`&QEH)5R^zH7CwY*sh{x$qE-NE4oa7=sPJbCvAp;FI0suz7n# zn2f&){5x&>-I{5$WK^9awt-|5zo& zQ_GQQnXP#p4;(k|c>jkE0ZIODrZe4)gzh_8w}>K1{o$Dc)f zMuPB)1oOXKL3m!}sg-ymwvzEzD<4DrZGrC#d>46=>Xh^eX-8dL^Q={+eqKY$U3Kf~ z9JQg2@n0Zbr8X#XK44V)s48{*D016tbjxT*{jG`d{l`uj>!@V{PaE4l%2AgK{N7lm zzCM;Y|0Hm;P~ziAA11I>;8cN!3S21g(*iFVNBO@m@i)g&hMMs#+bD4E_-W%E)j9sz zc&j=IP4XvoE?}!bM?El}7JFRa55`l%ze=f^?a1Na?a1vUiC-r18w5To@GYV5H-Q!_ zOjt6(QGEg*nZU9e1pZ^fd!Rclq>K`HkicVFDD#RI%67U?u9tYlMA~!o#1qm4k>>%E*j}p|VwJb~hTH>QyE77C0?-E8-Vr;b<3%`yD#$R8a1uU%+YPyQR z#peO5gICWG>~O(a4YpXYT@AKeusw)@%V&T!s>39$T76EioZ1b)NKmc51PK~(CvvXT zem&A+_@(5%q};8Na|u>Xk>+akEnuUug8CHFqVP!a?8dLslFRRe%gO3;Dfhml^{6X^ zX9Djy#vsGBDuJ9;g7vBg)fvEQfHkT<^^mflAFc{RzqM*)gxFZYt^h{6Op^^llxK)G3`kqkFL?S46l3-7%7ldb@V9%(Z zNx6%q+_UOW$f?wo!0PaordEsCHG*w4*v*1%HrTy_IT4-nn}Ssu>>0so4ECa64F=mN z*jR)8LaG)~K$FbPBdmu$v-_Ew+0#4v8AoEs>>yogvsaBF781QLy_W`0-o( zEx~Zzh%tVJRSOH=3@oM|0p_TGTB|Wa|4ZP9fHT$7=!nQnwOn99;Hd(80UdQlbWFr? z&WW}}7W7{fodkHfz-t8FAn-1M4-34`VxFfY{sV#Q1->ru7Xtqv@B@Ld81ttEHVfHDAn*!-*9&}5;L`$M0xW59l4wDAO_cBkfp-bK&LZV0 ziN6|S{09<$Q{wLm{FA^B1iB9M93=6)z?T47*U6w)JEs5+7dTqrI6yzO)%grkrwN=X zaA$#Y1nwUgMkzc$2_;1wJZp5BGM^ z_YpYXJriyHS;QT+#@zsTmb($~Y=NH__yxe3>N$6|HB-F^7*W4;=K}u0J;0i#9*IAN z_!Du~^&Nq4#lHi}Uj^EUXArLyI8NZ6iDyAMNMK&z(!}%d&te57=>=?2XIDh*h&mtf zh*~S~a)H-Y9DtlJSJc_`-o^Gbm9B)Bs!^3oZAXmOVB5l60`87|$&QI6SK7T-}qy8fBeS!ZH7^x*aCNLqeQeawOoxnzcqXmu?I6>eff$e~_ z>J2Vyzro$IY)hm2#5ryd76hIuuvg%!;rqlRs(<+PXu&TIr*B+0e1A|LAHE@SNdJ*_ ztJNX>%j?*(Y|V)JY#rfQbr&Gd#dTK!K2UcvU?lS)(?DVVXRHPNduBdB>I#9U2s}&R#R9(~ z@K%8j3w%o8_XWNv@Ku376ZoFMe+rD&lXI28MuBYtcNREb;86lk68IT`XA4{_@GAmu z7I>Gy2L(POaD%`%0ZY1Hl3dXLhkC-l3XC)`o)TCua5SKwe_X?tkvd7>RDrt)oF^~` z=;vJ0a1C;f6F5oW@qm8n$qm;_D&c7oUnB4=KtIm~4Ywop5`k9=yhh;l0&fv`x4?%0 zSxWb>yHVX9(O-|Bpbz^BSWm*ihh=0xBJ&Jeh}zyk$#3S1)aWPzs({Jg*~3A|3=EduWr_=v#o z2z)`{27x~p_&b6B6c`&BP5CV{d}I@(8X<6uz&3%?1@0tpUx5b-Tqtmnz@-8U0(%91 zUf`tyuMv2?z}p4hFYr-;-vjhzcy8o&kl`hPuL*op;5!1}1N3t~m6?Q`{~Adc8ATWq zm=IVaa1>y8WaF52TZ&^EVL{-jfDzR)Y6Hg1+^D+{FN}Hsuy51>R$9F|>48*QP0l`$ znx^g_^%}VSq~aOOlH)zj7p>lDHICZV>jiwciIndNe6i_tP{Mg`@a_w8zS#8mfYe9F zu&n0uZd1CpHuAmf>x~CDbIo~9L&QEEJCbDqb`Ewf{Q-79)}Rjr*d=%(@@9ZtiL->% zScSiHlxtsuJ=i#dRS7o3V597HNZZ$7E%w)eog&yTBOUe~IIXzcr0r_oi*uH58f_^{T-ZeTy3!BNUKw+?R477 z_Vf7A?kIz;0@kR`HQ0H`IZ|y1unpMDHBHdv)*@$-_J`OV{6w%{Mqaj~ksZ|ACT*jgjLcHid?8DHSG{dl z0b3;4IqDCBeM_**!2M0UbynA8`qk3Ob$QHL08eDv4YC4bIfGmti0 zy=1Vtz;;(-We0zGd~S3DcF>0#>>#A=rEUnY4R~Jm8-sNrZ9nyA!PYjMoOs#VU!8;d z4BA`Q;TM#@9AIN3`>T637Ju3~J2GEAYOo(UNnqbL*hc3(U@sc%9i$zgerB-0BJBWG z*)BE2Z8sS?P}OM+z2l3(_SBdf=3WswL>(DmS4R$2_X&1}8s*-LJN6UtWF2zG4+WRQ z)l`jv%Q~bj(wI8Zy$@+G8SFUsk;oCMV+zZyRR#B3kp*gwVCk#4m>RbX{cdEr z+I6~c0rt1ZN_Dis*#C;^_yDW0it1d0o$o%Vdeqkq#=hC3?hCMYBd4krd_;qB;>+&& zIOllYU|)A@tX1;q8K&LguEP!8=lN1Ay!>G|gR~8J;zaB+dyLhmc9C;e?YsTzO2N)i z-*T%W{pyz{jXj`W*?8DQ{a(fgNX}4c!M>~51I|=?3PvxVY@MktHCQ4#+4`LNn!)O$ zGc9}sVMnPwJ_Fdf>N5tL3+z1gGr_cfUZ9$GVou#+7pPqW?7YYY>PU@YlsfqTwD&IX zQ5RR=_{{wFN;b*vCgGw%!&Oi~0#QLh2}yuxLP8P*6vZW3l9f$1>~0{j=o>2ag0zao zYpE5A)+#D0TCDaFylb)57Ol3{YHM3-eY~`4)ko|5J!j_k+YJdmecu1`f8Y1>eiF#} z&G*dAnVB;)XU@#;67@~7&7jY{OVyR)b%QM54sn$zIfbS0=($Qv)=2n$OVw546oZO< z=c+BD#-L+;t?Jw2X$P%QTg9ANEJf7%HmGaF0fScfHmhsJ(%Cw$)%P8BohUq2m$$}u zi@ILm%{%<)HrybNbK9F7f#qiEclk zv_Y5nuah^4C8z1ST;hL4eNVI*bTd-kES@sxPDTd}dKmd`7L&?#zK4--yO?Fr&yaG5 zxWu4W8C_-2N65EB)X&xVK0?0li*pSM4cQ@fiVckZBquW3q~m<0L+(S|^#)Zky49ei zjP@9`cE}L9Q#@|a6^yt0jQR_L8bkH;Kd@eUAocFx-OL2oiv#l4cgW@g+{n~m_JZ8`u>vz^m z;(3FH=l#)oS#&Pcni!tU1$!az=#|{ht@p);2E7IJfheoj<(1`GuD^+!4f+&ue;2PCbQlVpgPQXKK)VfEn->E5nL#h)9Rc(!2bH)!5$_rF zTHZ0P&&2RXE%UX!DX!1OD1-izSLXUcOmfi4u78Se8uW2qxl71f9JIit~Uz`Q$!#?i|Hm;v+hFLniGxj{`p1@b(DqWM?2hRR(Abpj2OA31SbT*GDAnOe$4`8T+Z zlovYad#+;nph27RzvntyeqzuK`9E-tmc>hSz8muIbd8a-47xS{ew=xqXV4y?W8_9B z?jhF%xzmYz$aS22+@L4&A9GESZ#n20*YVP~RG09J{1;r)LP>A?bbmHZW>YeiFVxO<-b!l3hlN4u-#@Uykd^MVuHwX(^e zIO6JM+Cj&=o8)eTE(o6JULs#I=(6B!_gV5?gRTo!x|d52?sHQ;Zw;Q|K3A3)bZ@Z1 zeV%ML=qJIY?uhI*=;y(6-7Dqo2E7q%aW~672K^&=zPm;K$)Ma&r#mX&H|VI)TK6hB zmL3d6dB=y=yIbW_gXV`mx7uW{L5o5cyJK>bLFa@ncdwS)47w)i?Y zzCqs(Z3D_bSC{bZ&<=N}9B$C9q1)VRWTin5hVF7FW!#{D3q9yg%g+t^Y3Nb+S{YoS zrMwt=%DqlDG17LoTfW{*ab$P@EW72G4tm$UUQTVX<34gR0hP#&WP45FR)rSgD56eB+phk!9gc@u9w#uR34t~ zxl!(MP^ITPvbSC5YY5kPZj$dLG}?p`z9)BgYP7{_^lX=(8?+kbeP3=}qvKNHvpqZI zwxmV}kPnY-q%_(A^h24Kwo%k`hpaW|4r`p}PPy5jVxYTZNtaG}uhs6kTfT45UMuC< zEhnv|IK8{RS5`Bkb^2?b`{d;&j`kLN$e;?KpU8a2{_<9|8tnZ-bm-250y&e9O=Ox*Dp^key{O_J$NqG?= zt(RA1E~86)r3D{(UXkMsnpJSMctzG3G#_!lmTd+#A@0|5i$M{@{YKtyP#kf;kq0$` zc0cpHD$o5NR32&mBlkP9(?NOO_hfx9$BA_XVfDWJ{OcNB%;@HeHM*M7K7(j(zAvBN zsN=3LDD>h*n@b7N+#CVad6`C&!=t?)$*q@bR31Lo`wzKylSa1|O!Iyw&)clgLj^Ov z{~_bw)adDgO7B1AoNsCLGSHW@@Jfx|0ut&igFY!Z-7D3@SLrxc;ptwbuG*r}(88Hs zOWl06Mw?JGj|y(J(IT%;O}Iv*YpiA7A!^2T8tp*JTs7-EHd^G(S2f!-y2EPrhE&aW zH9CNlVfFA$8jUVI-&?3&-mcN4!e*QwJh?-o6M=@Q4-F~@8m^XnU&pNuH{*lW8x5*K z+!5+6gPICc-Xm4zPD-g~|4}N!h-UwK@6oE$#L?_8QL}E*DQWhXs0Fuj37GF+_m-#z zgZ!?qdq=Ak1`TtK@Qzh&290qwd&jFzgUS$hjOsC{0%)T8x`P&Zk5g9|REN09YO8}5 zd5>2&GrGjL#<$5^s%m~fb-BcMR^e6NX{zZqjn??C^OmWrerU&i*L$LR^>#vfcFa@@ z@8CF$-9O8js@*{kdS|Qa9Q3Yxj(W;Lk9y~-w;XhZs8C~e*;1bJR;gtg;mkO!=BcDX zv~tZ;8x5kBYo5B^pz+po-g)YAMzoJR=v|=xWa8+|xLOt8$tCcvu3Eip5Up`%s80-{ zHSP?x`7TOHbLH2#2mZc6QR@%hI(7ctI&O{iuD3z0H|PSOCgt0$<2E7RnJVs}k8zH( z&!8o{Lp?KNnxRqE?fA2QNoew_;KrIa-0XZpI;B1U=-+oLubL}R{3z0OFlcs;8AK`sF^ z;51*4`kq04*J-}5sa*yQbN$+Tq00NQPC3Tq^ZgGs!=N(6^{QVRK92CKMn(rqpQ-q6lh;OMGjA(queBV-W9fy27#FgrOlQLrM@?EL6 z{+rGhvF`U>jXyu2(ZfZ%eAlSk9CW|$dNpC6j-!*4@2G7CJzca^eMkBBa~z)*Zd1bz zTH|}fw@p2-k)Tt?@2a*(wG=u#yh)9HOrsZyp77nQUUtwf-ww6&aXapQoC%)yghsCw zJ?Fbkbw5dHgZQ}Upzn5d;3%FJk?N?@qPPpwGQe_;#zpXLKCZ z>|XV%gWUf6)Xryh9JO|jdS4@M-yZdaiKEldJu2s?I;G#|_TR6H4Jz{G_#aR$4l4BT zRl5v2);H4sV>Ri3&UdWu82>|Rr-M%NKdg$M({Z)F`Tn1%T?Vc2HTeHc&H9;+YxPC^ zkEl0)&IoP)$h}Yfhl3vVKBmIY+i|P?kE;_LbiH^|wK(Vs@szsOL05}s)FT?PReV;x zY!F$+XVu#VkyU(Fi5GNT##<@>vuY9}8g&=oiJXNdj;!Kys@ots>v~QFexdV`Rs6Y{ zWDr@!pQ~+*$SU^wUr_HD6tyn*|5DZblJZ?ERwM2u^^ieptgZf+)d7Pp0Q$9>aZsn+ zgp{wU%N(@L|C;)#L0gdWb@jPH*H}CKzgMTfsPmN!z03bc^>u@8gp@z2M-93O=q=@X zNvGTa^tM{$pl$wl)CPm@u=e=hReKC726|7G{YvM%*LukRzS?cjUTeSq1NFW^V~0ND z|GVmbS*P5Onti06Hs}D#`$P?YMaPXU{DuEB^}Io4Lx17_TqS-@aoS@3Q*CBM7V|g$ zFV&4Ej=Th6?K6lhrm%v)p?un63Tq7`+9SN-7uGEX`CV`Lm9@v9VXj_3j(A?BeAoKM zxc2xxR+&L%i1S(-4XOb0TQ4|hn?J{L{Z{9zaQ(%fYn}I+jeg<~t~nbF$TD&>hw#IkT+I z1{DL%wmvb4M)Ijv`b{l`M)GOa9)tFy^m6MD1|2{Nl~(YNI_2oXD|6;q>kTR!dS%W6 z>m^2d?4EA@oe_=Q8*|REz9K>9Jd5-OY%`?)ID->z4-kUE6aO zTAvv-%yoKBy>-l=xh@#Hm*g~93k)hlT%*-xPzBIpYlnjpIZLd^45~xiGV6T@C34QT z#=b=|^@u#j>SlC_@8aV7#5vaG8u40nj&;9-9?3b!`i+Ag&pFrnql12)v%(7gg=Ajh zyS6xJMXaxL+!pcD#C; z^#U$|^F^)Q8j1N6E(u4ir@xkoTV*}3k+>UitE?~AXX08d--V3Cdx)cVL-0&zF}+Q) z57ZKmf=cl?(`T7~ki#!$(cdxu4_Tb-l>g4LI@jMg{3)l@VfqY%C0w9V^pDL>`M(mj zgzvv7IiJ((_G)@0bB-LTpp&Bykv5S022OM4At?{vI$g@)+D@@b=vrl`(fsB8N@-z^ zmZ|A=9+Geqs3l??t99bz7A2X}i?9^E9R3EV65j%~#PueYdS^THzt8+zKwaVo9D6u^ zW(-*3hn(_Ij!WFj{C!#U&@@sU%CU24nc1T&6ShmtaHMz=r6}<%sAa};MxS;+X7}BT zociSd%+d94;;^o#JqxI;vpA)m(b@b6r_YYf*1w%H zGmox-mXv7WT&tP3GyPYzt)(TAUWp#gMfFr7+n)R@94$w;QPa$*u;=W>kZ%dHKQ6Hu zVRs*^^3}1F%N|`B$^RA3HQc)IGNsRcNujB(ZFcx}j@A78I80Ot-BX8#rTACVWJ~zZ za%D8B1oggUO8+YU;Zo{#=Wwz8`TaRxE#Yvn{~dB3bo8$^ro=lPE>jw@O8gCBOMJqdOwU@(cNzZwmz30BeM|W#zNKcbfQJj~ zUdF?YXyf5%W+d2SiPjM%XidReE4(V*0%{4}YBx*E&7#9NoNXnFkIvLh%OA^W4)tVQ zVlwlO2UX(a0n_wdajG~?J<|rxrTv`jRY|9@Z5^$oOSnGEK`pToREky1S=CQOIVG$mP)ihmy2LP0w>T2iBaR03iZP%* zaSW(m90xi?91of!rh^8=Nuasn6wo|z8fd<#01b-ypab`E|8Yer&p>)58aY??Xz4#r zwEoZL^yh=(uf=gLy}o4AOPIgep-NoC>A%aI>=JcYd!ZS=J;pK|yPn#Qy}6$p(y9_a zV7`w1Dyqb8u8$rY+2e2z_)0v;at;^Pk`EWF`H%FIK)EpQ*hW$5lIvi5al}#L$t*sF zZ9nsHR!Fy+c376NOPZr?lpbjrJ7e#{{`c>;bgQ4^HonMh{3=hz_L>g2U(4QM>0RVk zOQUh9gzmNMFy*!RUu~T-@(*7(t?jQ)*?$+N(`)@`Z@<^^^A+BIqj92lf|%6yB{GkI=FBoq{*3rh#)Jeoq!t z#i{t6D@IAWJ35hRDd;;n<)E8nHFFj*T?YF1oS3vmf0?re_Xhld9$7s4QFXaIX>>U7 zsVE;k5}fMMZLS_!Z@u7($s4U>12K6M=neAR(MQP}WXtHO2**dC2$~$7C)db(t=WM! zlJ3XcATJ%=5cr{x)+qTy@x9TJzz^l_(VOHbaCYE5E28(vgQGiGW-_oD`@gTtt<2xd zZ{lwj^j7{>eg}W6p!e}N^LsoG%6CU!6L?U5!c>iU8l_)4`nA9_XwfLSA8q+7YF=+W z#&!OkMRg{6+?X$O_H*6v)eWTF$#3iL;u3fA`}-8$Bwvv$$4t!KCC)0WSFgx64%1!L zUHq)pE+m7&pX`yJbJ!)XEpEiY0xK zpjgru35q3ssi0WWo9s8pFUEe9znyDHJ#xQ`#?@!c5y9;OqYhMB`Jg%Dek5*?!^RyO zyg`l{H$-k1lg1q%Eai8Lwu>*UGNd_obP>KbK=(-Y%d&AVTKnb6plcBRHR#EpFEll_RGCiacB+b#L(qxuXSRmROF1W2yIYn$5(@H8DAf| zN8L4kSqK`llA%|`qvL;sw=aG%zB_b}D05vHx z2#=C6`SLL|(_cI0OW21$F#R*=ezfK6a3xZH(^DqtI}Bx#zQaJAO_Jyid>x0LU@YZl z94mRgydwX4%*5O>`B2~{&kf?kV}@XUxhI?tIW&?h`Tdkies}K`Ib_1b+*y+54!(6^ zT^IISi3#5g)2O=-U)rI!aYtA*r)uQ(F+ryCmn&w{k1?>VgJ`lKa&)nTIv z)3+UN5aknpS?~e0cZo<#`p!dI(vu*itbq?iWa2A`ZJ)RU&rPN#o*$-h`+C7fNzZHC zBZj&DTo8w}Wxn;2-h+K-Z1ClKKL8g95@3|e| z_8w$pJs|HrxJPjk%=aLu1*dXVe?GS~lAuIKAq!#BBx zZ*dLZ;Tpb=y1B(Ckna|sL%ti1;dD@!JOMNyi64~2FJ%63<`>KL;FQRdK*!3NpcCXN zpp)cm(5dn?&@x#LIzv`~&XQH2bL4!`N_cy2u|Q6i0r8i<-@nQUU2&`c3uLlSHA&mQm=z9ReuCMk7HX9n=5?QMLwSh zSeN?n_s}eA%TkN#w%lq3J?MZG_X(@(`aPUuHYGmCT0;arvQV%?&KIrYqGV$M?6ZIHR#bvtMa=W1igahBZ4 zlG7}?npDgH#APn(+08EM*{fXCvs+!%v)8+*XScZ?7~&H*yB-4F>DmW+ zn@bMyiruc~K=-(w2i@!XCCc5$}cNVxw=QVgk$SvyKr1K^>X=bULX4Y~y_1bxE z8oe!eUkoGGO*1QwH^SVa(@irg?WUR4?LGr^J>LI6KrJQCtr#X+)v~Zd>&rErYsK|NAJq2G{{p*M+_@?KF zBQBO#$lTm97SW5DTCT^2yyPCk^bbs%J(l++_r*-V&-5{-Z%n*eRt=TMUM-gm9R<32 zXgTQmp%Kt)hi(A9XXtj&r-tqaeQoF)pdSvE$6YORhK&L(9##%|{ICdU`LGS34a2sB zwhr45df~7)K(8JqCtWRX8#W5`!C~c~FAj@aen z*YHtH%Rx5{kAU7Xd;{o@hHnQwFnmAg?}xtu`X9sPl&fXYh*6+ZN0ftBkBES-9I*lP zq7mCcuNkquj5M&H>EkCCh?m^1Q;3Qh;+HV>;bfuU2oF~0)9{caZqDHQx1Z&>0(pUP zfvUj5!16$ApgXWR@SVVefj<^DAH-P|#GoAR&B-O8)ElZ|5Hs92=Y!EDxR$tPh?YTor5&ZVuiU{6TPE@b|%wf`y^sp;e(vLR&)L z54{ljN5~&8437wp3Qq`64WAI66`mJv40ndNgl`GI8nz0C7L*hmTX1~AX$1=lmKB^= z&|1)5a8bdf1y>bZU+{jxX9b?ZnT2;378IRUlq&jG(cMMQ7QIvC9eVQ6dq=!H!iUoq zKkhXJ(8@gAVG4=@e3hmM=OsgNPI9Cu#*NpJI7=zzzj!yw`+cZjg7-GiQl=*}O=Z!G zyu0w=#1C`60Nu;IqP|nCVoeFk znqqp9_fBvw^4Fwje(HwAy{ zNYKlnHzhVfe@a{d4Jvq8V?eJG<3O(y$ADfhCW0=O$AO+BC!_RpK^1(k;}JfO=}K7& zPK4W@)=!x@1!rK@@Gh6&FK@Ik);K_pFh2snB z3R?>|6kb<&TjA@4e=Yp5@QXrkQLt!I(TPP%i&hrJi#FhU$&VGiTJ&a-7`k`F^CNt3 z)0d@Pz2cCcJ)`JuLgq(`a~SsJtzu}Q7wsP@eif$h5cFd{#&;oltO&o;(eg6z?7yI(>Rd{`Hk^dJEyHg6Jzm|sE8$-yW)|gUFc%^W_d%TM=VZLbbUOMUX@6;i-xX_bgVrp z7Ij4+s)JP{ykRLgdTrzc_^x~CeUf=(Tr7irerRJZbcba@4Yw4w_IIv5RT zM~Bu^Hqn%fM#cPOBn1`5W6i6}xi3t;(H)TssHGJR71O7Q_Ed8s8IP?LjXkM!v|XGT ziFfHjsw)!hoq9MRb#>JmXqUzYKxRbI7!$fW*qJs#hoXr^K#_JoS69YTorx6XHKk0! zc!{G0=&96{`OyyOq8YuXhZYGbWl__x&0QwW5>se+i<)RhYr4%`8c~~Mv_&jL|3~7n z3oy1jJCliSswIsau6nd7A*xgJVjUP^VqP-QKDQ?wO^Nx@v<@^S^tHUD1&WHacZ!N+ z0!l-D(~*wms1vYDtBkFUq01{1m=MuqCk9iusEu`q+OBvy)*0^+3!|;*6oGzBMbQmC zI?&jjNTk~u)6q`R*tHV<+?*DsqNvM)NUDuTQd2^Iv|ltO8Y1gVIMKO+lg83L0^#b8 zD7DZaR6NF02{DUlvT^w|{=u+|GSI0bqNp7-7bzLrmaddIE1FD*x{jz=40SDKx{T>r zqAA*)7Her>tXKio>W;*^4rX>G(W5l#MFnOT&zfWl##cv6dnCCUIz_X=MK7hJ%@IV+ zOT;ndMFaF76qNN9ekj6CBWb!n2L^@M#84-z8x*Ri) zr=Ko>E48HjOi|q)X=OniIK94Vz9{dAwMSTM^P?#$2ga-&9Zq8;vNl2H$gUgAn;;u! za8*Yt+Ky4&n5G)psEV53l}uv#)pey;#q5^#0ku6Eri`fCXsQiLGZUEf;Q(kt*e%SO z+Kz1|ZHl^NtTomF15%Ob>;dUWqj;F0wg`-SBP^d-5Q!y4RS(8{V_OW>t&ivg3F5#w zro`zHHtqA{iM8M@?m*9^I4K7^b^6tmw>;k277b8fV26sh*BzV^eiwAr%WVcXK4xkzy;G>_Lgz)N1<u4g{0ILl92}>ei zLJTl@4_Ry2H|#Dab|9Azf%R!(KsNLkjB+FE~|bM3Rc(24I97 z!hq+{h*^S_E|zwZaT=~`pIjLZrOrZBhN(NX-jQP$H&7gj7>KXe*{JTnlr3sOG~QxZ zPPtjU0R%a*#;lPfJtJsj7*B33*L4845ja2$7oXu%_h1P0m2Q~*gcyF72-bA19$i`C z#!eVN(vXRwD(fIOi(;@?EQzd+F79NXp%ac++8H?H991Nv;OJpN<<@oRa7A0Rc{MqV ziLNx60$anjzgpc_=hdmc`mRnLPS^ePJb;cJRv*G`E{0osnkpL&#du0>)!(9w#83v+=ZTs=3x+Ie-Ns8S}fagun$Q zJua?Ez!Jb`TN#7@(SRA7XeZYME@Zqb6nN~&L*=t%-w*r^?>J@coRyC{ubi(uM7B`5>s`)FL>Q*$AV{cJjNkMRILxsf= ze^$&kc@^;U;4rYUtLj*sGFVh%xX`!|RhUY`bdPo|jRkF_-4B#Cr6SqWnNGmg zb++}0+R78?cWzgVy`shi<=9w(WHF|la3ZmAv6&4E=fi&@pKC!h*$#7v<)t#(3YR~{ zj$=zK(g8aQF-Ao?y8$T9gtVIV_J#*@S4RhCqqC`^@vT|*_G*Q*eOwr6M`>_Ivo?{2 zXKy79JY;L4xvZL|M0H2H^hA*XS-}&_Y_PabDni*YnRL7o+fk-foYi*nwV(mf+*m8T znzS942~q^*vtzQtCeMjw*>Q(Kl$Psfr`7cv5M_#75bZWyWmMD`Wui6TmgewnMs*6T zO1O(@jF@iC&8`kBttp`uXlqF$Q)$g~_A`3#??9t$d$)r!_~fA}!G66nW}MxPU0o-p z?_os0bbUsdu*X-wWOf93AsEL^bnMY*S4^I=o|M#{R8xYj4w0q=bL=_45a%7$_1Ie_ zao~ZFj%GvE5$oo8jy)0wF!k)IZwHXtPSv;%DCl1R3sa43*UcVHS}8q}{X z6HDNhCDx_vYX$6AtfQ-2)HN;@wTX@d4(Bi-t8faGET@wf-o=)8$5M>QGd#bGx1M_K zqRnnrEU#z8V*%J6JB)?|Ha^%1>SGb^3EH|gqMS}q-4eyY3QT;XZQ>I+fWlD#+^;B~ z6KVI63?zBJ3FM?BDqaZ~(!Ls8Y!;G0Br)NT(L)0@`EI z!j5ewx8Bi+Q2`wVED=#U65~Q?jEfXDf0$r=P^PQWkE2I(BaMpHI1wWKW|FfIV$n8+ zt~mEQMBsqjETQGiG?*}~4v|U{`%CM`$&yr2Ua_ERMg8K2`Bf_xoF!_@m#(O(t2krD zlJe>%5lhu~C9%zJ6=^ypY{V&4q!oWjEelj**NkT?`0Q*7nFef5_`<1@P<=}s{QDMC z9PNr|`z8!7PbP7eNoEP>R8?`DX+-tLq&$h!L@GMUr;u4&!_utqG?84#dyLvhD?9={ zkLO0y>!O%}&WO+lWH>W`XGKSqqI@lm@silvuH$1u?48rGW}Ip0Z*awh)a` zI;Df2^==eLMX^;q2Jpdy=9hQ$)Y10N#4Jm6Y1r6|-8p4%N_4?3vW4JC6ebN_Ro{lW z1y|3p@a#AVKKon%wMTWZep8cjguOSM5 zu)}~xIIb%b-B??DXw2xUuqKS+nxgHU7(&UOx{ikE1;T;iEF8enktHoSr~~W;P6}aj zYvC`WjudQ+N1!(f)kiyMy6E##taeCC2jz6Qilado)9O^BDG4tS%Y;5=bWlUAwJq(S z1(EnFJ14Y&F=H}e=|SsR<}}ojeD-*>JI3d?X&Oj$4 zL=;C|j8mxESTYHtRgY8jxlv3@4$>!Gw^9M8!Yz`4? z9&MJG#Ua|TqUO;!&SWt$x^Tu_fm2f!T!op+DJejCaiE9&2o7sVq74?3y=Tti&Q3T8 zbW4QdvC87u2=`Qw(TUMD&=H(!0Zz~|nQNjjCX~4*u@1LofG7i{airKxCk4h}I~_Yw ziux$}pYl^+!Q#paxDe6gGzvB)IyuIK&4n^$5>jYx0_TkFHeaI*UyG=R&d`C8)flyj zP8@E<=XRyqN--qj?J$yw)^#*2v*U0KhPY`Mi#*M6|3e4Bhb+)IIW@5exnQWVEcS_|rsH7fQrV4&!$o?l_66XdHVw%!bBjq;VY_JRHHrJ4?mfDD=X2VoI4aP2ZN8 zsxPJbVwlr4D$^⁢xi?G#bL5-vV&XmmR5h6TvnwMwi!U*OgR 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 Lpa%Zm)WH7)14p@k From 392d270264610e7c20cb4becedc652843715ef30 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 31 May 2011 18:49:38 +0100 Subject: [PATCH 086/186] revert the patch that accidentally got added in the last commit --- .../Avatar/XmlRpcGroups/GroupsModule.cs | 27 ++++--------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 05223e067c..1c791b9d36 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1231,36 +1231,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId, dataForAgentID); GroupMembershipData[] membershipArray; - // c_scene and property accessor 'is_god' are in support of the opertions to bypass 'hidden' group attributes for - // those with a GodLike aspect. - Scene c_scene = (Scene) requestingClient.Scene; - bool is_god = c_scene.Permissions.IsGod(requestingClient.AgentId); - - if(is_god) { + if (requestingClient.AgentId != dataForAgentID) + { Predicate showInProfile = delegate(GroupMembershipData membership) { return membership.ListInProfile; }; - membershipArray = membershipData.ToArray(); + membershipArray = membershipData.FindAll(showInProfile).ToArray(); } else { - - if (requestingClient.AgentId != dataForAgentID) - { - Predicate showInProfile = delegate(GroupMembershipData membership) - { - return membership.ListInProfile; - }; - - membershipArray = membershipData.FindAll(showInProfile).ToArray(); - } - else - { - membershipArray = membershipData.ToArray(); - } + membershipArray = membershipData.ToArray(); } + if (m_debugEnabled) { m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); @@ -1273,7 +1257,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return membershipArray; } - private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); From 8129e64e2acea6509d5c3a80425f6aa68baa037c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 31 May 2011 19:25:01 +0100 Subject: [PATCH 087/186] Fill in the new OwnerData field in the LLUDP ScriptDialog message. If we don't do this then viewer 2.8 crashes. Resolves http://opensimulator.org/mantis/view.php?id=5510 --- OpenSim/Framework/IClientAPI.cs | 14 +++++++++- .../ClientStack/Linden/UDP/LLClientView.cs | 11 +++++--- .../CoreModules/Avatar/Dialog/DialogModule.cs | 3 ++- .../Examples/SimpleModule/MyNpcCharacter.cs | 2 +- .../Server/IRCClientView.cs | 2 +- .../Avatar/XmlRpcGroups/GroupsModule.cs | 27 +++++++++++++++---- .../OptionalModules/World/NPC/NPCAvatar.cs | 2 +- OpenSim/Tests/Common/Mock/TestClient.cs | 2 +- 8 files changed, 49 insertions(+), 14 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index f3ac2df085..137f432624 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1159,7 +1159,19 @@ namespace OpenSim.Framework void SendAgentAlertMessage(string message, bool modal); void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message, string url); - void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, + ///

+ /// Open a dialog box on the client. + /// + /// + /// + /// /param> + /// + /// + /// + /// + /// + /// + void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels); bool AddMoney(int debit); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5a2c45c1ad..821a370add 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -2213,7 +2213,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(loadURL, ThrottleOutPacketType.Task); } - public void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public void SendDialog( + string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, + UUID textureID, int ch, string[] buttonlabels) { ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); dialog.Data.ObjectID = objectID; @@ -2231,6 +2233,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]); } dialog.Buttons = buttons; + + dialog.OwnerData = new ScriptDialogPacket.OwnerDataBlock[1]; + dialog.OwnerData[0] = new ScriptDialogPacket.OwnerDataBlock(); + dialog.OwnerData[0].OwnerID = ownerID; + OutPacket(dialog, ThrottleOutPacketType.Task); } @@ -2293,8 +2300,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP OrbitalPosition = (OrbitalPosition - m_sunPainDaHalfOrbitalCutoff) * 0.6666666667f + m_sunPainDaHalfOrbitalCutoff; } - - SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); viewertime.TimeInfo.SunDirection = Position; viewertime.TimeInfo.SunAngVelocity = Velocity; diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index 8a977c9b44..0db31eb48f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -124,7 +124,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog ScenePresence sp = m_scene.GetScenePresence(avatarID); if (sp != null) - sp.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); + sp.ControllingClient.SendDialog( + objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); } public void SendUrlToUser( diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 89e9e204bb..56b46d7f44 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -540,7 +540,7 @@ namespace OpenSim.Region.Examples.SimpleModule { } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 4b6e52e757..88db20ef8a 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -1177,7 +1177,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server IRC_SendChannelPrivmsg(objectname,url); } - public void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 1c791b9d36..05223e067c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1231,20 +1231,36 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId, dataForAgentID); GroupMembershipData[] membershipArray; - if (requestingClient.AgentId != dataForAgentID) - { + // c_scene and property accessor 'is_god' are in support of the opertions to bypass 'hidden' group attributes for + // those with a GodLike aspect. + Scene c_scene = (Scene) requestingClient.Scene; + bool is_god = c_scene.Permissions.IsGod(requestingClient.AgentId); + + if(is_god) { Predicate showInProfile = delegate(GroupMembershipData membership) { return membership.ListInProfile; }; - membershipArray = membershipData.FindAll(showInProfile).ToArray(); + membershipArray = membershipData.ToArray(); } else { - membershipArray = membershipData.ToArray(); - } + if (requestingClient.AgentId != dataForAgentID) + { + Predicate showInProfile = delegate(GroupMembershipData membership) + { + return membership.ListInProfile; + }; + + membershipArray = membershipData.FindAll(showInProfile).ToArray(); + } + else + { + membershipArray = membershipData.ToArray(); + } + } if (m_debugEnabled) { m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); @@ -1257,6 +1273,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return membershipArray; } + private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 2504e3019c..15bc1b7644 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -631,7 +631,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index dca562674b..bf91ab5817 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -637,7 +637,7 @@ namespace OpenSim.Tests.Common.Mock { } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } From c67fa72d5628725581b61b7a16c37955e154006d Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 31 May 2011 19:57:08 +0100 Subject: [PATCH 088/186] When sending an LLUDP MoneyBalanceReply message, fill out the transaction item description even though there is none. This is to deal with a problem in libomv where calling ToBytes() without this crashes because of an ItemDescription.Lnegth dereference. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 821a370add..d8fcb6223d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1469,6 +1469,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP money.MoneyData.TransactionSuccess = success; money.MoneyData.Description = description; money.MoneyData.MoneyBalance = balance; + money.TransactionInfo.ItemDescription = Util.StringToBytes256("NONE"); OutPacket(money, ThrottleOutPacketType.Task); } From 5711ada5c98bb6769eb5454380945791c14227e0 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 31 May 2011 22:42:18 +0100 Subject: [PATCH 089/186] Fix dumb sql mistake in MSSQLGenericTableHandler.Delete() --- OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs index 317afac493..ab9df4c6c5 100644 --- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs +++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs @@ -358,7 +358,7 @@ namespace OpenSim.Data.MSSQL string where = String.Join(" AND ", terms.ToArray()); - string query = String.Format("DELETE * FROM {0} WHERE {1}", m_Realm, where); + string query = String.Format("DELETE FROM {0} WHERE {1}", m_Realm, where); cmd.Connection = conn; cmd.CommandText = query; From aed6e74080a23bab148c085140e412aa0ba0aef2 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Wed, 1 Jun 2011 13:44:20 -0400 Subject: [PATCH 090/186] Add alternate region handling for url based logins as found in login to "home" or "last" --- .../Services/LLLoginService/LLLoginService.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index a5a728be78..5d1779a15c 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -516,6 +516,7 @@ namespace OpenSim.Services.LLLoginService // free uri form // 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+)$"); Match uriMatch = reURI.Match(startLocation); if (uriMatch == null) @@ -546,8 +547,18 @@ namespace OpenSim.Services.LLLoginService } else { - m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, Grid does not provide default regions.", startLocation); - return null; + m_log.Info("[LLOGIN SERVICE]: Last Region Not Found Attempting to find random region"); + region = FindAlternativeRegion(scopeID); + if (region != null) + { + where = "safe"; + return region; + } + else + { + m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, Grid does not provide default regions and no alternative found.", startLocation); + return null; + } } } return regions[0]; @@ -575,7 +586,8 @@ namespace OpenSim.Services.LLLoginService if (parts.Length > 1) UInt32.TryParse(parts[1], out port); - GridRegion region = FindForeignRegion(domainName, port, regionName, out gatekeeper); +// GridRegion region = FindForeignRegion(domainName, port, regionName, out gatekeeper); + region = FindForeignRegion(domainName, port, regionName, out gatekeeper); return region; } } From 8bacf56e46413edaf2d6afc227ff6bb5f2ac4d4d Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 1 Jun 2011 20:51:38 +0100 Subject: [PATCH 091/186] revert the prematurely included groups patch, yet again --- .../Avatar/XmlRpcGroups/GroupsModule.cs | 27 ++++--------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 05223e067c..1c791b9d36 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1231,36 +1231,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId, dataForAgentID); GroupMembershipData[] membershipArray; - // c_scene and property accessor 'is_god' are in support of the opertions to bypass 'hidden' group attributes for - // those with a GodLike aspect. - Scene c_scene = (Scene) requestingClient.Scene; - bool is_god = c_scene.Permissions.IsGod(requestingClient.AgentId); - - if(is_god) { + if (requestingClient.AgentId != dataForAgentID) + { Predicate showInProfile = delegate(GroupMembershipData membership) { return membership.ListInProfile; }; - membershipArray = membershipData.ToArray(); + membershipArray = membershipData.FindAll(showInProfile).ToArray(); } else { - - if (requestingClient.AgentId != dataForAgentID) - { - Predicate showInProfile = delegate(GroupMembershipData membership) - { - return membership.ListInProfile; - }; - - membershipArray = membershipData.FindAll(showInProfile).ToArray(); - } - else - { - membershipArray = membershipData.ToArray(); - } + membershipArray = membershipData.ToArray(); } + if (m_debugEnabled) { m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); @@ -1273,7 +1257,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return membershipArray; } - private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); From c43ad8a0e7728c41ed2a4aed6a8b76678aaa7071 Mon Sep 17 00:00:00 2001 From: James Stallings aka Hiro Protagonist Date: Tue, 31 May 2011 19:33:40 -0500 Subject: [PATCH 092/186] A final couple of tweaks to GroupsModule.cs. Remove unneeded delegate, and prettify codeing style/formatting --- .../Avatar/XmlRpcGroups/GroupsModule.cs | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 1c791b9d36..61c550300c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1223,6 +1223,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// /// Get a list of groups memberships for the agent that are marked "ListInProfile" + /// (unless that agent has a godLike aspect, in which case get all groups) /// /// /// @@ -1231,20 +1232,31 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId, dataForAgentID); GroupMembershipData[] membershipArray; - if (requestingClient.AgentId != dataForAgentID) - { - Predicate showInProfile = delegate(GroupMembershipData membership) - { - return membership.ListInProfile; - }; + // cScene and property accessor 'isGod' are in support of the opertions to bypass 'hidden' group attributes for + // those with a GodLike aspect. + Scene cScene = (Scene) requestingClient.Scene; + bool isGod = cScene.Permissions.IsGod(requestingClient.AgentId); - membershipArray = membershipData.FindAll(showInProfile).ToArray(); + if (isGod) { + membershipArray = membershipData.ToArray(); } else { - membershipArray = membershipData.ToArray(); - } + if (requestingClient.AgentId != dataForAgentID) + { + Predicate showInProfile = delegate(GroupMembershipData membership) + { + return membership.ListInProfile; + }; + + membershipArray = membershipData.FindAll(showInProfile).ToArray(); + } + else + { + membershipArray = membershipData.ToArray(); + } + } if (m_debugEnabled) { m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); @@ -1257,6 +1269,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return membershipArray; } + private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); From a3e0895f12fa81074138a356c01fbcbc40d6aba2 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 1 Jun 2011 20:55:03 +0100 Subject: [PATCH 093/186] a few minor formatting tweaks --- .../OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 61c550300c..630fcabac3 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1234,15 +1234,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // cScene and property accessor 'isGod' are in support of the opertions to bypass 'hidden' group attributes for // those with a GodLike aspect. - Scene cScene = (Scene) requestingClient.Scene; + Scene cScene = (Scene)requestingClient.Scene; bool isGod = cScene.Permissions.IsGod(requestingClient.AgentId); - if (isGod) { + if (isGod) + { membershipArray = membershipData.ToArray(); } else { - if (requestingClient.AgentId != dataForAgentID) { Predicate showInProfile = delegate(GroupMembershipData membership) @@ -1257,6 +1257,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups membershipArray = membershipData.ToArray(); } } + if (m_debugEnabled) { m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); From 5fb0455e929d96efb41d23f67653b329792ab834 Mon Sep 17 00:00:00 2001 From: Chris Hart Date: Wed, 1 Jun 2011 04:01:18 +0100 Subject: [PATCH 094/186] Updates to MSSQL to most recent compatibility, also included Windlight support. Needs plenty of testing but clean install and migration from 0.6.9 have been tested and work, a few indexes still need to be added for performance. --- OpenSim/Data/MSSQL/MSSQLEstateData.cs | 203 ++++++- OpenSim/Data/MSSQL/MSSQLFriendsData.cs | 1 - .../Data/MSSQL/MSSQLGenericTableHandler.cs | 22 +- OpenSim/Data/MSSQL/MSSQLMigration.cs | 32 +- OpenSim/Data/MSSQL/MSSQLRegionData.cs | 1 + OpenSim/Data/MSSQL/MSSQLSimulationData.cs | 513 +++++++++++++++++- OpenSim/Data/MSSQL/MSSQLXInventoryData.cs | 32 +- .../Data/MSSQL/Resources/Avatar.migrations | 24 + .../MSSQL/Resources/GridUserStore.migrations | 46 ++ .../MSSQL/Resources/RegionStore.migrations | 2 +- 10 files changed, 828 insertions(+), 48 deletions(-) diff --git a/OpenSim/Data/MSSQL/MSSQLEstateData.cs b/OpenSim/Data/MSSQL/MSSQLEstateData.cs index d10ebe4f48..9c54e77a23 100644 --- a/OpenSim/Data/MSSQL/MSSQLEstateData.cs +++ b/OpenSim/Data/MSSQL/MSSQLEstateData.cs @@ -41,7 +41,7 @@ namespace OpenSim.Data.MSSQL { private const string _migrationStore = "EstateStore"; - private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private MSSQLManager _Database; private string m_connectionString; @@ -72,7 +72,12 @@ namespace OpenSim.Data.MSSQL } //Migration settings - _Database.CheckMigration(_migrationStore); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + Migration m = new Migration(conn, GetType().Assembly, "EstateStore"); + m.Update(); + } //Interesting way to get parameters! Maybe implement that also with other types Type t = typeof(EstateSettings); @@ -112,19 +117,19 @@ namespace OpenSim.Data.MSSQL { FieldInfo f = _FieldMap[name]; object v = reader[name]; - if (f.FieldType == typeof(bool) ) + if (f.FieldType == typeof(bool)) { f.SetValue(es, Convert.ToInt32(v) != 0); } - else if (f.FieldType == typeof(UUID) ) + else if (f.FieldType == typeof(UUID)) { f.SetValue(es, new UUID((Guid)v)); // uuid); } - else if (f.FieldType == typeof(string)) + else if (f.FieldType == typeof(string)) { f.SetValue(es, v.ToString()); } - else if (f.FieldType == typeof(UInt32)) + else if (f.FieldType == typeof(UInt32)) { f.SetValue(es, Convert.ToUInt32(v)); } @@ -186,7 +191,7 @@ namespace OpenSim.Data.MSSQL } catch (Exception e) { - _Log.DebugFormat("[ESTATE DB]: Error inserting regionID and EstateID in estate_map: {0}", e); + m_log.DebugFormat("[ESTATE DB]: Error inserting regionID and EstateID in estate_map: {0}", e); } } @@ -310,12 +315,12 @@ namespace OpenSim.Data.MSSQL conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { - cmd.CommandText = "delete from estateban where EstateID = @EstateID"; + cmd.CommandText = "delete from estateban where EstateID = @EstateID"; cmd.Parameters.AddWithValue("@EstateID", (int)es.EstateID); cmd.ExecuteNonQuery(); //Insert after - cmd.CommandText = "insert into estateban (EstateID, bannedUUID) values ( @EstateID, @bannedUUID )"; + cmd.CommandText = "insert into estateban (EstateID, bannedUUID,bannedIp, bannedIpHostMask, bannedNameMask) values ( @EstateID, @bannedUUID, '','','' )"; cmd.Parameters.AddWithValue("@bannedUUID", Guid.Empty); foreach (EstateBan b in es.EstateBans) { @@ -350,43 +355,195 @@ namespace OpenSim.Data.MSSQL public EstateSettings LoadEstateSettings(int estateID) { - // TODO: Implementation! - return new EstateSettings(); + EstateSettings es = new EstateSettings(); + string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) + " from estate_settings where EstateID = @EstateID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateID", (int)estateID); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + foreach (string name in FieldList) + { + FieldInfo f = _FieldMap[name]; + object v = reader[name]; + if (f.FieldType == typeof(bool)) + { + f.SetValue(es, Convert.ToInt32(v) != 0); + } + else if (f.FieldType == typeof(UUID)) + { + f.SetValue(es, new UUID((Guid)v)); // uuid); + } + else if (f.FieldType == typeof(string)) + { + f.SetValue(es, v.ToString()); + } + else if (f.FieldType == typeof(UInt32)) + { + f.SetValue(es, Convert.ToUInt32(v)); + } + else if (f.FieldType == typeof(Single)) + { + f.SetValue(es, Convert.ToSingle(v)); + } + else + f.SetValue(es, v); + } + } + + } + } + } + LoadBanList(es); + + es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers"); + es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users"); + es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups"); + + //Set event + es.OnSave += StoreEstateSettings; + return es; + } - + public List LoadEstateSettingsAll() { - // TODO: Implementation! - return new List(); + List allEstateSettings = new List(); + + List allEstateIds = GetEstatesAll(); + + foreach (int estateId in allEstateIds) + allEstateSettings.Add(LoadEstateSettings(estateId)); + + return allEstateSettings; } public List GetEstates(string search) { - // TODO: Implementation! - return new List(); + List result = new List(); + string sql = "select estateID from estate_settings where EstateName = @EstateName"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateName", search); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(Convert.ToInt32(reader["EstateID"])); + } + reader.Close(); + } + } + } + + return result; } - + public List GetEstatesAll() { - // TODO: Implementation! - return new List(); + List result = new List(); + string sql = "select estateID from estate_settings"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(Convert.ToInt32(reader["EstateID"])); + } + reader.Close(); + } + } + } + + return result; } public List GetEstatesByOwner(UUID ownerID) { - return new List(); + List result = new List(); + string sql = "select estateID from estate_settings where EstateOwner = @EstateOwner"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateOwner", ownerID); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(Convert.ToInt32(reader["EstateID"])); + } + reader.Close(); + } + } + } + + return result; } public bool LinkRegion(UUID regionID, int estateID) { - // TODO: Implementation! + string sql = "insert into estate_map values (@RegionID, @EstateID)"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + try + { + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@RegionID", regionID); + cmd.Parameters.AddWithValue("@EstateID", estateID); + + int ret = cmd.ExecuteNonQuery(); + return (ret != 0); + } + } + catch (Exception ex) + { + m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message); + } + } return false; } public List GetRegions(int estateID) { - // TODO: Implementation! - return new List(); + List result = new List(); + string sql = "select RegionID from estate_map where EstateID = @EstateID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateID", estateID); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(DBGuid.FromDB(reader["RegionID"])); + } + reader.Close(); + } + } + } + + return result; } public bool DeleteEstate(int estateID) diff --git a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs index 0b178f14cc..09dde5e182 100644 --- a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs +++ b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs @@ -89,6 +89,5 @@ namespace OpenSim.Data.MSSQL return DoQuery(cmd); } } - } } diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs index ab9df4c6c5..4145d957ba 100644 --- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs +++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs @@ -168,14 +168,13 @@ namespace OpenSim.Data.MSSQL protected T[] DoQuery(SqlCommand cmd) { + List result = new List(); using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader == null) return new T[0]; - CheckColumnNames(reader); - - List result = new List(); + CheckColumnNames(reader); while (reader.Read()) { @@ -262,6 +261,15 @@ namespace OpenSim.Data.MSSQL { names.Add(fi.Name); values.Add("@" + fi.Name); + // Temporarily return more information about what field is unexpectedly null for + // http://opensimulator.org/mantis/view.php?id=5403. This might be due to a bug in the + // InventoryTransferModule or we may be required to substitute a DBNull here. + if (fi.GetValue(row) == null) + throw new NullReferenceException( + string.Format( + "[MSSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null", + fi.Name, row)); + if (constraintFields.Count > 0 && constraintFields.Contains(fi.Name)) { constraints.Add(new KeyValuePair(fi.Name, fi.GetValue(row).ToString())); @@ -363,7 +371,13 @@ namespace OpenSim.Data.MSSQL cmd.Connection = conn; cmd.CommandText = query; conn.Open(); - return cmd.ExecuteNonQuery() > 0; + + if (cmd.ExecuteNonQuery() > 0) + { + //m_log.Warn("[MSSQLGenericTable]: " + deleteCommand); + return true; + } + return false; } } } diff --git a/OpenSim/Data/MSSQL/MSSQLMigration.cs b/OpenSim/Data/MSSQL/MSSQLMigration.cs index cd395b84d1..1aa96c7ff0 100644 --- a/OpenSim/Data/MSSQL/MSSQLMigration.cs +++ b/OpenSim/Data/MSSQL/MSSQLMigration.cs @@ -29,16 +29,19 @@ using System; using System.Data; using System.Data.Common; using System.Reflection; +using System.Data.SqlClient; namespace OpenSim.Data.MSSQL { public class MSSQLMigration : Migration { - public MSSQLMigration(DbConnection conn, Assembly assem, string type) : base(conn, assem, type) + public MSSQLMigration(DbConnection conn, Assembly assem, string type) + : base(conn, assem, type) { } - public MSSQLMigration(DbConnection conn, Assembly assem, string subtype, string type) : base(conn, assem, subtype, type) + public MSSQLMigration(DbConnection conn, Assembly assem, string subtype, string type) + : base(conn, assem, subtype, type) { } @@ -67,5 +70,30 @@ namespace OpenSim.Data.MSSQL } return version; } + + protected override void ExecuteScript(DbConnection conn, string[] script) + { + if (!(conn is SqlConnection)) + { + base.ExecuteScript(conn, script); + return; + } + + foreach (string sql in script) + { + try + { + using (SqlCommand cmd = new SqlCommand(sql, (SqlConnection)conn)) + { + cmd.ExecuteNonQuery(); + } + } + catch (Exception ex) + { + throw new Exception(sql); + + } + } + } } } diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs index cdf8ec09fb..3ae87c3804 100644 --- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs @@ -70,6 +70,7 @@ namespace OpenSim.Data.MSSQL string sql = "select * from ["+m_Realm+"] where regionName like @regionName"; if (scopeID != UUID.Zero) sql += " and ScopeID = @scopeID"; + sql += " order by regionName"; using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand(sql, conn)) { diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs index 5155e567e6..78f80e154a 100644 --- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs +++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs @@ -55,6 +55,10 @@ namespace OpenSim.Data.MSSQL ///

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 z zy2H_0d^L#q`bLype2wY4PX|j^!{#;4?`3fie3E^1trltd>~! z0ca=d_mGNM_L|P=5x|ub0=zi__|b#_=f=pbkJ%MzcUPnZU}vNSU}DlAiIMwq%&thU z+ZAa6*coX7n3(k4F>=qu?25FvE7Ah6GtvSuG3jUl+5F7r*4L#LoxVF-tzc#4PPh{F3W-A$~r<&Pe|+#V@&T7vkpw?2PpPQv8zZ zb|HQ~z|KhjFU2ppZWrR`1MH0SB*pJ1p~ztu!gjjd&`#WC8*wXIjd&YjIu>Tou*YNE z_6XhK%vxN_W5$^CMO=mAjEXE*Vfr*!sR!vckM3B&bQOXtITn^>Pg5qVDJ`*yL;G2r_Su`Z(ZowN?zw^`G?chRc0 z85-XE=xCls((A?gbU(01Xoa4w?H-=9j0>7Wn!Jv;i0c%3YC1#LdHrqRM{6uYM;VrYptxWyazD# zZr!D6pN{m`vGOMl+)S3$^)d5Nbbh0CACF-Q!dV9@_ESi`a#!rX(C!z|dqX%`DAHYK zvAZCL*kk6c#Q6_E+gB#A@G|IftquNn(LaH#SG!QcMQA{9g%1#S5+WZ$giFYP;2bX? zenyCuU|!(}7ySXjg&IKIO^7KWj&M;K5L}x9#2tj_4k5xNVL-?zY0UfyAD*il5C<68-6ubKX#(d6~mSbTlrE_Vm%PK%5>M7l{z72HM z%Mf4A4B=i8e>+Iz zk+0>P_JkjrPdgUu>m5LDxE{PJl&qBsFL!j*2X+BfH6u=77uFV&M95kp?K0`4714KjPCYgPojnG%zaVW2VXjQ?RgYKZ#J}qs}p| zw1ElxkJJ!R`y|TAIu6>u-iA3umaSTi-gi9E1R4ygF&FPf-h#HOnQ&i)Pr}up920Jve0BL6_}ULcM5~VTIPe?R_Yli@ z7FOM5C&*d>^@+3@+JV6T9pK0M_xc-HFgKDd9WhInX=}0_nsp>Vb7sn_u)J3yG;8+P z`Wv9a@g$v35%>`S zCeJvG5x^#q(xBq7{#5+@(cR17^0xM(s+iupVb@)Ded}0LrD=BAO{B-^O)^UeD@jul zz%-DKhCb(akv9qV5dh>;y~__m3qoJ*H2kV4lZO!C)AU`!4TNMoedq9rNGWbcJ`Qv( zj8%Q*;Fq^jB}!k|Yr*)CS>MNTfYEfB#u)Ru%YHf2Nz+d!_+cI_NI}i0%(xUzzZLBV zEjpFb>hfrZ7gd<`5CxHWaRE4#@)4zG*cX8b2w|W~`>dY=Qn6{+Z$}`Mu!G@dRKN7bqbRTB-ptEwB#2SF~Nn$j!2ju$}Feg{}GtE+UE zBaAw>3(-uteXJ=nQGu%~beF>wrb#S@J)Pd<;bElx04^ccaasy_u6AEZp8Epr{1D!L z-=!j1k+=wYr45_-A4iD&dseEl?z?8dWzWM$1|+7_WyV3o6@kb=1ruWXpz{;?N;6_Q zYg&C(t76@PqVQx?EJi=t5}UL;Z4oAI0dA7|q83 zggM7Viq(@@Ffi{T4Hq8bV_M4)m`j!C=A2H1`$+;WV_sV0*&6;ihayOI2IG|@VLy+^ z9-C0rWu)R(?W@w?y30&-E=Oz`GxldI*6)PlA3E3V0Od^bwlmoz%F~CjsS_u09sH>J|zK*efACO)N$_9#<^FF zbDtt^Al^vI$TI_N-BM;A{y>J_DvBGbQFkXa zbR4xGP_~`~LSGtHAHe&Nq)WbI=EI0Nt}~ED+ExFJFlM|rK-_6<7%jjLC0*Mgc^rKP zWDNbOEp|&!q%C~i0Cn)>qLy0CHbb8#HNbQhv2KgvIN5iw`iok@uDn@cXj%7Nk#<-I zJSpc;5Dzqu?}|V?l5z>iLZzwJXEuQb>V&ffk+*9YA!;J#5xnjaQKhURe-4?MPnYLb zoEs1wXXRwdY9&yHm6US|e?Zy%2>I8k88&ucnbtd@oIB9~awcOo0`d3k66;;?W%V>Y zncO15eudc!Qy|tT@YH@SGL0m+tha1`hUtD}d+Xfc zQ}Bte#hFe%v)#(uB6_t#9Sg4xbNrm6>0C+B)J_)MZUunz7(TJ}9NpnY$M{sGwC&;9 zt!PmZI-lDL{dK0_`m=6j?{?&%E<4q|J7{%Y0R`_)u};atdKax_?`{~?59!uz$ZS;O zpV2qr{hUV9;}n73p71zBP(5DnFByrX#jQs4`~^L43S({~Y{I*bM$)^VMtjoxrI@Do zE0{6hU(-9`JwPMr{YHQi-fzWBdJn>^J{MwUml41Z(@1)w0+jF`5i{vMDyHfEPRx|| zdzi7vkI_5fv1^UU>_n4yXdPh>LmZf<_k@@!@6Rw}Y+^ve$n0Mu@>2qo@SYYk={*Cp zDs2GA1pEtG{wqNe-m^54-rpob!h254r1y6*P49UzQ{D?=ro9(o##qOQi%9-SBkBE1 zfD+zIVkW(p#WcNF#7uerhFRSfa=@_2buvbaTwZV&SNV>E^g6mfi%t6CTG1 zh-3;7cCU+>^wKb^PDmj`?}V47k@Rv5jLIyp0t+gzod(Evh?(@Jh-rF7F;iYA%oyep zy%Sy+jifh~foOEgzFDDpp^EsB3_|fO4Md&iis_GGo7+Mu<-d= z=w_$wcfxA_4$+E<$}*n8$ZR@)_*WQQvQINzr!=Ea*b7b3EMwey$@@UwIX84(PUlxc z=lkh=DRf>z=YhE(?g!}H6gsb@^MTNL6`iy40q_PoSBK7xbbcdrZlY5w1i&Ap^YGAl zHJu*`otx<#4V@pN(`pamewa=tbbf@+TSMnHbebIj@JH!9HgtZB&Ml$yS~?#Kogb%j z&XgeT7CPS**=6gode=XIg;({w%=I;LiE|@=Io!bqkN3sFHqHn_6r|td-6Aa}64To>a=DHtq zMrF+06AUy*Q0Z{;g={~3IU?Xl%lqLNI2f~M3!2V9kqngwa$3Y%18~(3#6Du&0w5`y z6!uDf)EwfmwAtzUPo0lV-5#&%;mgUj;Jnk@w0Su1v=aHEX|R7zGhP;ZNt=J5_8#RA z`%jfW&jGRB`)RBk8zZ{KoHlGshiBKGY~nZw<~Yc=p>o2$0_pW`lUXLa0Z^Y$P44N? zv}xMReKkYTf_r9I1q)v2?Nm|Pkqk9zCAM2KQ{uK;{$B5D83kX;9%~3q+?FRfe zV1A^Wt<5UuYEyM(gy}6OzOtzmard)4s zqHjv9AEdQFYyZ;zrOm79WSQs*Yaa3#4e76lADvDbx=WWVoqAb94cv|_Yc2<*XVUEh z?16!WdlOVtb2AaLR^j??=|G z4*_?T?eE!Aawy08O5JS-My?#wwA&#dy4&G<(e%Bh_+B)9FXk8{(zHJe+`7yo)NwqN z%Yzl$#L^(v`ApvHqG5vo&+}1)lz`!Qp>+WGGC27s*~HyNWsVF4YJZNa$nvb|RSI9b}5~Qzt9?7@PA(IvOPLx2EYjI}20%p`9 z(Z)3A0=~fn1i5#B zwNs$xbxs(RW>Aq>OzSY@CFmN^{TKT(>I>CEWxAK@$WS>Y$Vrit%UG*v$(%^?FzZ7{ zJTtz{%-CHWP;9j8n4(T1y9BK2d=jWIAMcT%c>N^d&f!fCv0 z3KrD>rmVdvn%1ynD(B$d3g+)(*?p-XW%vG$Fn=f-s+6vPr|FIll2ZCW6tpfaJo8&w zW_^TO>&gfl_llUhy#)e+Y?QeY(!QItzolqj6+uU|Hwc08K|*_D6f^}no#zIM*oykvI%^0u$?xg4c619Ku0rHs(;D~bJ-Rg zb}uH=?mLk{gsw1_U3*fcn#7n#(@v7JzU+S<1bz2&&@; zQnJ=pG*v`gh43+OS4{MBaGt~vJy}fjEt71V+o8Mc;dGidPWxsXcR{}Pst54~WjLSQ zw$KN{d-k8JKPysjqt(#bbROh)StqN=2#&aif^>OfZmw_~aM_;# zqVoKiD#+dnm;Fh6a@aERDVRerKMfOI@{GFIteKfj?do3K0~IL^`k>n{JVM`X^JqmP zU4$wa(_2ToRQR&@ZpgZxmgX$p8<>GufjsM4hcg)eXciB@`n>Q-Xf|a~FIxx<)SzYdJ<9NZi=&jHp+?91K@~e&xzlvuHI{SI3 zfa*uFVD%Zqtn27()eVEg0tIEnpymLIIMe`@^$r^?wQZom^ZBfK_VqxbhDB?!!Kh8# zLZWe;ub@!wW#@CEDN;}>97y>ZB-QPFOZoT2QLF-k*B4WwRpQM%R=2%2 zrvj{%tO&rma!7iWbp?8NL#k}ob-~|yKRryP@Gqf`FZ!W945j=Bp==K7C;6b#930jv z|Ine+l}`*PeU1G&A`$Hw^T)K>eNh!Lr3n%3wBT5C?Y&7&$8v|NTp6hloUwxrqF2WK zWjDomi~B2>3Vk?TCt*N-Kal%%!lz2%9>LIE^WE=(o2P%NGjI{g=fS0N*k2H9qyWDL z1vs42trHJ3t%%&nU6RmPtf|rs@pESEhO8zm<`mAbes5dSHrTeHm(bS3N*F^Kz?dE@= z1oO=oW@=_3gH;xYNjhVH5uUZKiF{k4Hy&<2jfkB5jj6?AB5nUC5O|cmw0#4tIdlL- zS8~ijU49b!HTQ!bC8kPwFFp{SfhZ@&>-LS0ArN^^v9`YioMzenG7JbW_US>LJR}Wb zuAE=^cM2GKC>fWnsRy?R#J6`eP-(95Y zbuyM2DvqkkNPAMHUFnQX=Pya1|ARaZ?uQ*bP_>`BR&VQCs^lq$xt%#kHvfW}YP|_H z(;tzyL5?}}Rzq<+PqpVy^ZEU>vet!Zel=b+wEKVu+y0B?RoU{YoJz7wO`7-Z6kO;i z&Ux7Xg(8dRE2l(;F`poTHzE+BoB`P(pac>SlFUeH`zwNy{u!~GMo|=r!XF&rLs(SiTyN>F6F1Y`@+6pj_xvg z5RHD<*f#;y5aQAm#T8d}G#6f}T&|iy|Ei!hFH!vyEXr|p36op@&D>0QH`7RZUx$HY zXq1_GF!^VF1DFM1Ebb=rChMjfXu5UwWP z+7s;wH6ivh__546M$xso+I;_B=~;T0MR+>Fva3&6 z4z9u`qlzt;nEeL&He>E>U}AD8%@lWsN~%T*HFs7ABI_34&6WR zXW?btqfj40R$2kbw%i3hq@D0CC2u-ztUdoS4J$uto`Uu9H*vmmPIq4*hz7)RFSz{u zONu}2z$2fyiHk<_m-ysxCrhVp{|eSZDr5f|rs!bZr3lXdqtQsMe*m^xm-QPMB@_J# zmx5^hmd=EkDkho_(u%=7Wq~)0Yub>U`;lx@3j(;>>>)tK7X(zf6tqlPrH}3D7ZLZj zJ4%x;IwjSNbY-z%fN>HtHiaZeh8NQI!*G}9C(_wkK^6~G*t-6#BNJ~LeAoz z+l!%T+M|GLK7vmnQ%XdQ6>e2mX_&2D{K;T^r)wif!-Km>LvTrSC`+wNEWXUn(%R<* zdMyyncp&Ixs zS8M9RoNMHqtxWY_5g*N}_>((q#h!(sehC8?Amkci3HTlnd?%vEkTvURENmfv&*eAwKcVx_coXh2ZM=HEi;I1OZ6_bv!f-z9l zB__oIr&y5U2i^5*2rq8K2D<} z>5)is{S6#!-H1=U=sb#wgJ~g#tChGYGTu;7NwqeT4c3p3fj(~0fE-FjbZYhsAk`>4 z3L|Y}$7t5A7#lA1tZSt?%_`cr{-{RIK<2%ro$?{{auo=XPPf z<)5(TQ)wv#`(JRtZ$3C~{9!bY6A~#nhv9rERfq<|nV=tZsy5S8eIII&6E_C!Z9@Af zhTDG#`5z3s2ZsA66sgLX)!}-b)BeHGhFLqBT*HL2%Q4 z2@I<|Rg2o+#fYz7sx)6_s?rLJjr$VAXcVYULo##ZJILdVeFv~|lA%7+tj|!wC}M|u ze<_$^w-l=Yng{P#UYjy__WgWueHJ;4yz*bTFza($N+%^Tl$VN-v7b^g{O30^rhO*} z>!J&>n>!9XrG5n2cOU8ah@`M!`Yw1SwlZ72uAgm63DoyeW-N2n41CNxp1;9Fdpzm(zmaluaHxAF>7QWIJ$wQvk+C)@ z{ra3#jFw+%lvkWiH~|!n2q60w^JqV!RL3`i zA=L4N#>=<jW}uf7poDOB<1grr( zj&wKi*lQL821A`_N>44dKfDlOMvvr2Uh<<*>&>KXyxE#vi#<>}1~;f}cwaTkaYWk2 zGpO0Lox^wdfzfQbZl-_S7IndJlDP^)xil^*&r^2qm>W^m+MfcqY6*)EoH#jHeAu6!}){tJ4nm=|Nt#nU$8 z5Jg*QN^wfrIUNbPzBr{45PAZDaCggH?6C9{bL$vcgb40l=Nl?UUoqbjU|r2@<7Muc zF}LqQ`iiLlsWi(}t6?%1Vg@xzB6A~1-Ca@Y%3=m_sc&IWvB#4L`(II6DQRIsQRsN?HM{6lT*Zz`)G=1Z z^=|$XUzoecJFVFUmK?FnnXVZS8~BOH6l9+wW}FNlhET4^>#s&xMr`ZtCol@H-v9nfS3z68_ux zrD4I7PO37)P5)=`;aT1S>LqnQ|2SS?+wiAQzZ;_Z!7gPRX94jxf*+o!ACr($F;p8m z;`|m#=)n2TZ&)>}%7F1@&`bG>l}et>V#Io0>>AKa0em&mt&H z8&AT=1K6dPsqb{NcGx?2jQ&VVTx(vVc6`Z^Bd?@2zeW?xMGez znB}A1m$|!wcGQZ1ep1^FDhp2ppufsUr7 z*W7E}QUadO%0)gadvzLdRt%pNV|!LIF;=P*aWb=%a4rEWXqi@pZA}X=RimCZWLSG`eh;wf4@U_!qDU=ET z%0A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º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�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%0AMu`T=o*KB4-M+tR7Uol%=S2i8riz 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 z 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

private MSSQLManager _Database; private string m_connectionString; + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } public MSSQLSimulationData() { @@ -74,9 +78,28 @@ namespace OpenSim.Data.MSSQL m_connectionString = connectionString; _Database = new MSSQLManager(connectionString); + using (SqlConnection conn = new SqlConnection(connectionString)) + { + conn.Open(); + //New Migration settings + Migration m = new Migration(conn, Assembly, "RegionStore"); + m.Update(); - //Migration settings - _Database.CheckMigration(_migrationStore); + // Clean dropped attachments + // + try + { + using (SqlCommand cmd = conn.CreateCommand()) + { + cmd.CommandText = "delete from prims where prims.UUID in (select UUID from primshapes where PCode = 9 and State <> 0); delete from primshapes where PCode = 9 and State <> 0"; + cmd.ExecuteNonQuery(); + } + } + catch (Exception ex) + { + _Log.Error("[REGION DB]: Error cleaning up dropped attachments: " + ex.Message); + } + } } /// @@ -214,7 +237,7 @@ namespace OpenSim.Data.MSSQL { command.Parameters.Clear(); command.Parameters.Add(_Database.CreateParameter("@PrimID", objectPart.UUID)); - + List inventory = new List(); using (SqlDataReader reader = command.ExecuteReader()) @@ -241,6 +264,14 @@ namespace OpenSim.Data.MSSQL /// public void StoreObject(SceneObjectGroup obj, UUID regionUUID) { + uint flags = obj.RootPart.GetEffectiveObjectFlags(); + // Eligibility check + // + if ((flags & (uint)PrimFlags.Temporary) != 0) + return; + if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) + return; + _Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Parts.Length); using (SqlConnection conn = new SqlConnection(m_connectionString)) @@ -700,16 +731,470 @@ VALUES } public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) { - //This connector doesn't support the windlight module yet - //Return default LL windlight settings - return new RegionLightShareData(); + RegionLightShareData nWP = new RegionLightShareData(); + nWP.OnSave += StoreRegionWindlightSettings; + string sql = "select * from [regionwindlight] where region_id = @regionID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@regionID", regionUUID)); + conn.Open(); + using (SqlDataReader result = cmd.ExecuteReader()) + { + if (!result.Read()) + { + //No result, so store our default windlight profile and return it + nWP.regionID = regionUUID; + StoreRegionWindlightSettings(nWP); + return nWP; + } + else + { + nWP.regionID = DBGuid.FromDB(result["region_id"]); + nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); + nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); + nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); + nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); + nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); + nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); + nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); + nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); + nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); + nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); + nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); + nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); + nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); + nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); + nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); + nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); + nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); + UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); + nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); + nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); + nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); + nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); + nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); + nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); + nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); + nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); + nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); + nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); + nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); + nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); + nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); + nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); + nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); + nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); + nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); + nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); + nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); + nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); + nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); + nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); + nWP.eastAngle = Convert.ToSingle(result["east_angle"]); + nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); + nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); + nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); + nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); + nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); + nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); + nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); + nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); + nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); + nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); + nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); + nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); + nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); + nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); + nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); + nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); + nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); + nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); + nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); + nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); + nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); + nWP.valid = true; + } + } + } + return nWP; } + public void RemoveRegionWindlightSettings(UUID regionID) { + string sql = "delete from [regionwindlight] where region_id = @region_id"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + conn.Open(); + cmd.Parameters.Add(_Database.CreateParameter("@region_id", regionID)); + cmd.ExecuteNonQuery(); + } } + public void StoreRegionWindlightSettings(RegionLightShareData wl) { - //This connector doesn't support the windlight module yet + string sql = "select count (region_id) from regionwindlight where region_id = @region_id"; + bool exists = false; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@region_id", wl.regionID)); + exists = (int)cmd.ExecuteScalar() > 0; + } + } + if (exists) + { + RemoveRegionWindlightSettings(wl.regionID); + } + + // sql insert + sql = @"INSERT INTO [regionwindlight] + ([region_id] + ,[water_color_r] + ,[water_color_g] + ,[water_color_b] + ,[water_fog_density_exponent] + ,[underwater_fog_modifier] + ,[reflection_wavelet_scale_1] + ,[reflection_wavelet_scale_2] + ,[reflection_wavelet_scale_3] + ,[fresnel_scale] + ,[fresnel_offset] + ,[refract_scale_above] + ,[refract_scale_below] + ,[blur_multiplier] + ,[big_wave_direction_x] + ,[big_wave_direction_y] + ,[little_wave_direction_x] + ,[little_wave_direction_y] + ,[normal_map_texture] + ,[horizon_r] + ,[horizon_g] + ,[horizon_b] + ,[horizon_i] + ,[haze_horizon] + ,[blue_density_r] + ,[blue_density_g] + ,[blue_density_b] + ,[blue_density_i] + ,[haze_density] + ,[density_multiplier] + ,[distance_multiplier] + ,[max_altitude] + ,[sun_moon_color_r] + ,[sun_moon_color_g] + ,[sun_moon_color_b] + ,[sun_moon_color_i] + ,[sun_moon_position] + ,[ambient_r] + ,[ambient_g] + ,[ambient_b] + ,[ambient_i] + ,[east_angle] + ,[sun_glow_focus] + ,[sun_glow_size] + ,[scene_gamma] + ,[star_brightness] + ,[cloud_color_r] + ,[cloud_color_g] + ,[cloud_color_b] + ,[cloud_color_i] + ,[cloud_x] + ,[cloud_y] + ,[cloud_density] + ,[cloud_coverage] + ,[cloud_scale] + ,[cloud_detail_x] + ,[cloud_detail_y] + ,[cloud_detail_density] + ,[cloud_scroll_x] + ,[cloud_scroll_x_lock] + ,[cloud_scroll_y] + ,[cloud_scroll_y_lock] + ,[draw_classic_clouds]) + VALUES + (@region_id + ,@water_color_r + ,@water_color_g + ,@water_color_b + ,@water_fog_density_exponent + ,@underwater_fog_modifier + ,@reflection_wavelet_scale_1 + ,@reflection_wavelet_scale_2 + ,@reflection_wavelet_scale_3 + ,@fresnel_scale + ,@fresnel_offset + ,@refract_scale_above + ,@refract_scale_below + ,@blur_multiplier + ,@big_wave_direction_x + ,@big_wave_direction_y + ,@little_wave_direction_x + ,@little_wave_direction_y + ,@normal_map_texture + ,@horizon_r + ,@horizon_g + ,@horizon_b + ,@horizon_i + ,@haze_horizon + ,@blue_density_r + ,@blue_density_g + ,@blue_density_b + ,@blue_density_i + ,@haze_density + ,@density_multiplier + ,@distance_multiplier + ,@max_altitude + ,@sun_moon_color_r + ,@sun_moon_color_g + ,@sun_moon_color_b + ,@sun_moon_color_i + ,@sun_moon_position + ,@ambient_r + ,@ambient_g + ,@ambient_b + ,@ambient_i + ,@east_angle + ,@sun_glow_focus + ,@sun_glow_size + ,@scene_gamma + ,@star_brightness + ,@cloud_color_r + ,@cloud_color_g + ,@cloud_color_b + ,@cloud_color_i + ,@cloud_x + ,@cloud_y + ,@cloud_density + ,@cloud_coverage + ,@cloud_scale + ,@cloud_detail_x + ,@cloud_detail_y + ,@cloud_detail_density + ,@cloud_scroll_x + ,@cloud_scroll_x_lock + ,@cloud_scroll_y + ,@cloud_scroll_y_lock + ,@draw_classic_clouds)"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("region_id", wl.regionID)); + cmd.Parameters.Add(_Database.CreateParameter("water_color_r", wl.waterColor.X)); + cmd.Parameters.Add(_Database.CreateParameter("water_color_g", wl.waterColor.Y)); + cmd.Parameters.Add(_Database.CreateParameter("water_color_b", wl.waterColor.Z)); + cmd.Parameters.Add(_Database.CreateParameter("water_fog_density_exponent", wl.waterFogDensityExponent)); + cmd.Parameters.Add(_Database.CreateParameter("underwater_fog_modifier", wl.underwaterFogModifier)); + cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X)); + cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y)); + cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z)); + cmd.Parameters.Add(_Database.CreateParameter("fresnel_scale", wl.fresnelScale)); + cmd.Parameters.Add(_Database.CreateParameter("fresnel_offset", wl.fresnelOffset)); + cmd.Parameters.Add(_Database.CreateParameter("refract_scale_above", wl.refractScaleAbove)); + cmd.Parameters.Add(_Database.CreateParameter("refract_scale_below", wl.refractScaleBelow)); + cmd.Parameters.Add(_Database.CreateParameter("blur_multiplier", wl.blurMultiplier)); + cmd.Parameters.Add(_Database.CreateParameter("big_wave_direction_x", wl.bigWaveDirection.X)); + cmd.Parameters.Add(_Database.CreateParameter("big_wave_direction_y", wl.bigWaveDirection.Y)); + cmd.Parameters.Add(_Database.CreateParameter("little_wave_direction_x", wl.littleWaveDirection.X)); + cmd.Parameters.Add(_Database.CreateParameter("little_wave_direction_y", wl.littleWaveDirection.Y)); + cmd.Parameters.Add(_Database.CreateParameter("normal_map_texture", wl.normalMapTexture)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_r", wl.horizon.X)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_g", wl.horizon.Y)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_b", wl.horizon.Z)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_i", wl.horizon.W)); + cmd.Parameters.Add(_Database.CreateParameter("haze_horizon", wl.hazeHorizon)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_r", wl.blueDensity.X)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_g", wl.blueDensity.Y)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_b", wl.blueDensity.Z)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_i", wl.blueDensity.W)); + cmd.Parameters.Add(_Database.CreateParameter("haze_density", wl.hazeDensity)); + cmd.Parameters.Add(_Database.CreateParameter("density_multiplier", wl.densityMultiplier)); + cmd.Parameters.Add(_Database.CreateParameter("distance_multiplier", wl.distanceMultiplier)); + cmd.Parameters.Add(_Database.CreateParameter("max_altitude", wl.maxAltitude)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_r", wl.sunMoonColor.X)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_g", wl.sunMoonColor.Y)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_b", wl.sunMoonColor.Z)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_i", wl.sunMoonColor.W)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_position", wl.sunMoonPosition)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_r", wl.ambient.X)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_g", wl.ambient.Y)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_b", wl.ambient.Z)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_i", wl.ambient.W)); + cmd.Parameters.Add(_Database.CreateParameter("east_angle", wl.eastAngle)); + cmd.Parameters.Add(_Database.CreateParameter("sun_glow_focus", wl.sunGlowFocus)); + cmd.Parameters.Add(_Database.CreateParameter("sun_glow_size", wl.sunGlowSize)); + cmd.Parameters.Add(_Database.CreateParameter("scene_gamma", wl.sceneGamma)); + cmd.Parameters.Add(_Database.CreateParameter("star_brightness", wl.starBrightness)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_r", wl.cloudColor.X)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_g", wl.cloudColor.Y)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_b", wl.cloudColor.Z)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_i", wl.cloudColor.W)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_x", wl.cloudXYDensity.X)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_y", wl.cloudXYDensity.Y)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_density", wl.cloudXYDensity.Z)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_coverage", wl.cloudCoverage)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scale", wl.cloudScale)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_x", wl.cloudDetailXYDensity.X)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_y", wl.cloudDetailXYDensity.Y)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_density", wl.cloudDetailXYDensity.Z)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_x", wl.cloudScrollX)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_x_lock", wl.cloudScrollXLock)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_y", wl.cloudScrollY)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_y_lock", wl.cloudScrollYLock)); + cmd.Parameters.Add(_Database.CreateParameter("draw_classic_clouds", wl.drawClassicClouds)); + + cmd.ExecuteNonQuery(); + } + } + #region update + // } + // else + // { + // // sql update + // sql = @"UPDATE [OpenSim].[dbo].[regionwindlight] + // SET [region_id] = @region_id + // ,[water_color_r] = @water_color_r + // ,[water_color_g] = @water_color_g + // ,[water_color_b] = @water_color_b + // ,[water_fog_density_exponent] = @water_fog_density_exponent + // ,[underwater_fog_modifier] = @underwater_fog_modifier + // ,[reflection_wavelet_scale_1] = @reflection_wavelet_scale_1 + // ,[reflection_wavelet_scale_2] = @reflection_wavelet_scale_2 + // ,[reflection_wavelet_scale_3] = @reflection_wavelet_scale_3 + // ,[fresnel_scale] = @fresnel_scale + // ,[fresnel_offset] = @fresnel_offset + // ,[refract_scale_above] = @refract_scale_above + // ,[refract_scale_below] = @refract_scale_below + // ,[blur_multiplier] = @blur_multiplier + // ,[big_wave_direction_x] = @big_wave_direction_x + // ,[big_wave_direction_y] = @big_wave_direction_y + // ,[little_wave_direction_x] = @little_wave_direction_x + // ,[little_wave_direction_y] = @little_wave_direction_y + // ,[normal_map_texture] = @normal_map_texture + // ,[horizon_r] = @horizon_r + // ,[horizon_g] = @horizon_g + // ,[horizon_b] = @horizon_b + // ,[horizon_i] = @horizon_i + // ,[haze_horizon] = @haze_horizon + // ,[blue_density_r] = @blue_density_r + // ,[blue_density_g] = @blue_density_g + // ,[blue_density_b] = @blue_density_b + // ,[blue_density_i] = @blue_density_i + // ,[haze_density] = @haze_density + // ,[density_multiplier] = @density_multiplier + // ,[distance_multiplier] = @distance_multiplier + // ,[max_altitude] = @max_altitude + // ,[sun_moon_color_r] = @sun_moon_color_r + // ,[sun_moon_color_g] = @sun_moon_color_g + // ,[sun_moon_color_b] = @sun_moon_color_b + // ,[sun_moon_color_i] = @sun_moon_color_i + // ,[sun_moon_position] = @sun_moon_position + // ,[ambient_r] = @ambient_r + // ,[ambient_g] = @ambient_g + // ,[ambient_b] = @ambient_b + // ,[ambient_i] = @ambient_i + // ,[east_angle] = @east_angle + // ,[sun_glow_focus] = @sun_glow_focus + // ,[sun_glow_size] = @sun_glow_size + // ,[scene_gamma] = @scene_gamma + // ,[star_brightness] = @star_brightness + // ,[cloud_color_r] = @cloud_color_r + // ,[cloud_color_g] = @cloud_color_g + // ,[cloud_color_b] = @cloud_color_b + // ,[cloud_color_i] = @cloud_color_i + // ,[cloud_x] = @cloud_x + // ,[cloud_y] = @cloud_y + // ,[cloud_density] = @cloud_density + // ,[cloud_coverage] = @cloud_coverage + // ,[cloud_scale] = @cloud_scale + // ,[cloud_detail_x] = @cloud_detail_x + // ,[cloud_detail_y] = @cloud_detail_y + // ,[cloud_detail_density] = @cloud_detail_density + // ,[cloud_scroll_x] = @cloud_scroll_x + // ,[cloud_scroll_x_lock] = @cloud_scroll_x_lock + // ,[cloud_scroll_y] = @cloud_scroll_y + // ,[cloud_scroll_y_lock] = @cloud_scroll_y_lock + // ,[draw_classic_clouds] = @draw_classic_clouds + // WHERE region_id = @region_id"; + // using (SqlConnection conn = new SqlConnection(m_connectionString)) + // { + // conn.Open(); + // using (SqlCommand cmd = new SqlCommand(sql, conn)) + // { + // cmd.Parameters.AddWithValue("region_id", wl.regionID); + // cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); + // cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); + // cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); + // cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); + // cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); + // cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); + // cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); + // cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); + // cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); + // cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); + // cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); + // cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); + // cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); + // cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); + // cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); + // cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); + // cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); + // cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); + // cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); + // cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); + // cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); + // cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); + // cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); + // cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); + // cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); + // cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); + // cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); + // cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); + // cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); + // cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); + // cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); + // cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); + // cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); + // cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); + // cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); + // cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); + // cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); + // cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); + // cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); + // cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); + // cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); + // cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); + // cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); + // cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); + // cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); + // cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); + // cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); + // cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); + // cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); + // cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); + // cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); + // cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); + // cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); + // cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); + // cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); + // cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); + // cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); + // cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); + // cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); + // cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); + // cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock); + // cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds); + + // cmd.ExecuteNonQuery(); + // } + // } + // } + #endregion } /// /// Loads the settings of a region. @@ -1136,7 +1621,7 @@ VALUES if (Convert.ToInt16(primRow["PassTouches"]) != 0) prim.PassTouches = true; prim.LinkNum = Convert.ToInt32(primRow["LinkNumber"]); - + if (!(primRow["MediaURL"] is System.DBNull)) prim.MediaUrl = (string)primRow["MediaURL"]; @@ -1192,11 +1677,11 @@ VALUES { } - if (!(shapeRow["Media"] is System.DBNull) ) + if (!(shapeRow["Media"] is System.DBNull)) { baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]); } - + return baseShape; } @@ -1576,15 +2061,15 @@ VALUES parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams)); parameters.Add(_Database.CreateParameter("State", s.State)); - if(null == s.Media ) + if (null == s.Media) { - parameters.Add(_Database.CreateParameter("Media", DBNull.Value)); + parameters.Add(_Database.CreateParameter("Media", DBNull.Value)); } else { - parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml())); + parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml())); } - + return parameters.ToArray(); } diff --git a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs index 01689a43e6..10b0f2938f 100644 --- a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs +++ b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs @@ -66,11 +66,18 @@ namespace OpenSim.Data.MSSQL public bool StoreFolder(XInventoryFolder folder) { + if (folder.folderName.Length > 64) + folder.folderName = folder.folderName.Substring(0, 64); return m_Folders.Store(folder); } public bool StoreItem(XInventoryItem item) { + if (item.inventoryName.Length > 64) + item.inventoryName = item.inventoryName.Substring(0, 64); + if (item.inventoryDescription.Length > 128) + item.inventoryDescription = item.inventoryDescription.Substring(0, 128); + return m_Items.Store(item); } @@ -78,7 +85,6 @@ namespace OpenSim.Data.MSSQL { return m_Folders.Delete(field, val); } - public bool DeleteFolders(string[] fields, string[] vals) { return m_Folders.Delete(fields, vals); @@ -88,12 +94,10 @@ namespace OpenSim.Data.MSSQL { return m_Items.Delete(field, val); } - public bool DeleteItems(string[] fields, string[] vals) { return m_Items.Delete(fields, vals); } - public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); @@ -172,5 +176,27 @@ namespace OpenSim.Data.MSSQL } } + public override bool Store(XInventoryItem item) + { + if (!base.Store(item)) + return false; + string sql = "update inventoryfolders set version=version+1 where folderID = @folderID"; + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + conn.Open(); + + cmd.Parameters.AddWithValue("@folderID", item.parentFolderID.ToString()); + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + return false; + } + } + return true; + } } } diff --git a/OpenSim/Data/MSSQL/Resources/Avatar.migrations b/OpenSim/Data/MSSQL/Resources/Avatar.migrations index 5364153363..61f7b562d2 100644 --- a/OpenSim/Data/MSSQL/Resources/Avatar.migrations +++ b/OpenSim/Data/MSSQL/Resources/Avatar.migrations @@ -37,4 +37,28 @@ EXECUTE sp_rename N'dbo.Tmp_Avatars', N'Avatars', 'OBJECT' COMMIT +:VERSION 3 + +BEGIN TRANSACTION + +CREATE TABLE dbo.Tmp_Avatars + ( + PrincipalID uniqueidentifier NOT NULL, + [Name] varchar(32) NOT NULL, + Value text NOT NULL DEFAULT '', + PRIMARY KEY CLUSTERED +( + [PrincipalID] ASC, [Name] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] + TEXTIMAGE_ON [PRIMARY] + +IF EXISTS(SELECT * FROM dbo.Avatars) + EXEC('INSERT INTO dbo.Tmp_Avatars (PrincipalID, Name, Value) + SELECT PrincipalID, CONVERT(text, Name), Value FROM dbo.Avatars WITH (HOLDLOCK TABLOCKX)') + +DROP TABLE dbo.Avatars + +EXECUTE sp_rename N'dbo.Tmp_Avatars', N'Avatars', 'OBJECT' +COMMIT diff --git a/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations b/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations index 7a7cecdb40..ecd3f4dbda 100644 --- a/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations +++ b/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations @@ -17,3 +17,49 @@ CREATE TABLE "GridUser" ( ) COMMIT + +:VERSION 2 # -------------------------- + +BEGIN TRANSACTION + +CREATE TABLE [GridUser_tmp] ( + [UserID] VARCHAR(255) NOT NULL, + [HomeRegionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', + [HomePosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [HomeLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [LastRegionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', + [LastPosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [LastLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [Online] CHAR(5) NOT NULL DEFAULT 'false', + [Login] CHAR(16) NOT NULL DEFAULT '0', + [Logout] CHAR(16) NOT NULL DEFAULT '0', + + PRIMARY KEY CLUSTERED + ( + [UserID] ASC + )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + ) ON [PRIMARY] + +COMMIT + +IF EXISTS(SELECT * FROM dbo.GridUser) + EXEC('INSERT INTO dbo.GridUser_tmp ([UserID] + ,[HomeRegionID] + ,[HomePosition] + ,[HomeLookAt] + ,[LastRegionID] + ,[LastPosition] + ,[LastLookAt] + ,[Online] + ,[Login] + ,[Logout]) + SELECT CONVERT(varchar(36), [HomeRegionID]), [HomePosition] ,[HomeLookAt] , CONVERT(varchar(36),[LastRegionID]) + ,[LastPosition] + ,[LastLookAt] + ,[Online] + ,[Login] + ,[Logout] FROM dbo.GridUser WITH (HOLDLOCK TABLOCKX)') + +DROP TABLE dbo.GridUser + +EXECUTE sp_rename N'dbo.GridUser_tmp', N'GridUser', 'OBJECT' \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations index 340b63dec3..3995e6ce2c 100644 --- a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations @@ -1003,7 +1003,7 @@ CREATE TABLE "regionwindlight" ( PRIMARY KEY ("region_id") ) -COMMIT TRANSACTION +COMMIT :VERSION 26 From 54096db30b1b0a93de6bd3913e7000b55039b71a Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Tue, 31 May 2011 22:24:51 +0900 Subject: [PATCH 095/186] Fix: The command line switches 'save_crashes' and 'crash_dir' haven't actually worked --- OpenSim/Region/Application/Application.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index 7e320e6798..63c535de9d 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -239,6 +239,8 @@ namespace OpenSim configSource.AddSwitch("Startup", "physics"); configSource.AddSwitch("Startup", "gui"); configSource.AddSwitch("Startup", "console"); + configSource.AddSwitch("Startup", "save_crashes"); + configSource.AddSwitch("Startup", "crash_dir"); configSource.AddConfig("StandAlone"); configSource.AddConfig("Network"); From b0ed0e63dcc2c364b623ec2bf887c0a2fec8f80b Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Tue, 31 May 2011 21:38:32 +0900 Subject: [PATCH 096/186] Adding boolean alias for commandline switches like -save_crashes=yes --- OpenSim/Region/Application/Application.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index 63c535de9d..3b261e77dd 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -231,6 +231,8 @@ namespace OpenSim configSource.Alias.AddAlias("Off", false); configSource.Alias.AddAlias("True", true); configSource.Alias.AddAlias("False", false); + configSource.Alias.AddAlias("Yes", true); + configSource.Alias.AddAlias("No", false); configSource.AddSwitch("Startup", "background"); configSource.AddSwitch("Startup", "inifile"); From 4b9e446c6267a1161263d885699e72c97e8a94eb Mon Sep 17 00:00:00 2001 From: BlueWall Date: Wed, 1 Jun 2011 16:57:01 -0400 Subject: [PATCH 097/186] Use current TravelingAgent if the login failure reason is "Logins Disabled" to fix NullReferenceException, allowing agent to login to fallback region when logins are disabled by "StartDisabled = true" or when logins are disabled by RegionReady --- OpenSim/Services/HypergridService/UserAgentService.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 387547e252..2f2ebfba5a 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -197,8 +197,11 @@ namespace OpenSim.Services.HypergridService agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason); // restore the old travel info - lock (m_TravelingAgents) - m_TravelingAgents[agentCircuit.SessionID] = old; + if(reason != "Logins Disabled") + { + lock (m_TravelingAgents) + m_TravelingAgents[agentCircuit.SessionID] = old; + } return false; } From 0a430bbffb561a5172220e7617257798c11a66f5 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Wed, 1 Jun 2011 18:10:56 -0400 Subject: [PATCH 098/186] Revert "Use current TravelingAgent if the login failure reason is "Logins Disabled" to fix NullReferenceException, allowing agent to login to fallback region when logins are disabled by "StartDisabled = true" or when logins are disabled by RegionReady" This reverts commit 4b9e446c6267a1161263d885699e72c97e8a94eb. --- OpenSim/Services/HypergridService/UserAgentService.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 2f2ebfba5a..387547e252 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -197,11 +197,8 @@ namespace OpenSim.Services.HypergridService agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason); // restore the old travel info - if(reason != "Logins Disabled") - { - lock (m_TravelingAgents) - m_TravelingAgents[agentCircuit.SessionID] = old; - } + lock (m_TravelingAgents) + m_TravelingAgents[agentCircuit.SessionID] = old; return false; } From 777f57d9469d4df11ea2bf2bd0704f89cae34b0a Mon Sep 17 00:00:00 2001 From: BlueWall Date: Wed, 1 Jun 2011 18:47:06 -0400 Subject: [PATCH 099/186] Re-Apply Use current TravelingAgent if the the login failure reason is "Logins Disabled" to fix NullReferenceException, allowing agent to login to fallback region when logins are disabled by "StartDisabled = true" or when logins are disabled by RegionReady"" This reverts commit 0a430bbffb561a5172220e7617257798c11a66f5. --- OpenSim/Services/HypergridService/UserAgentService.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 387547e252..2f2ebfba5a 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -197,8 +197,11 @@ namespace OpenSim.Services.HypergridService agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason); // restore the old travel info - lock (m_TravelingAgents) - m_TravelingAgents[agentCircuit.SessionID] = old; + if(reason != "Logins Disabled") + { + lock (m_TravelingAgents) + m_TravelingAgents[agentCircuit.SessionID] = old; + } return false; } From 46cdd442a8daebe5b1573f09cd5cef51c0b17874 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 1 Jun 2011 18:18:31 -0700 Subject: [PATCH 100/186] [Profiles] --> [Profile] --- .../Region/CoreModules/Avatar/Profile/BasicProfileModule.cs | 4 ++-- bin/config-include/Grid.ini | 2 +- bin/config-include/GridHypergrid.ini | 2 +- bin/config-include/Standalone.ini | 2 +- bin/config-include/StandaloneHypergrid.ini | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs index e04fff6c78..079e1b6b0a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs @@ -57,9 +57,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile public void Initialise(IConfigSource config) { - if (config.Configs["Profiles"] != null) + if (config.Configs["Profile"] != null) { - if (config.Configs["Profiles"].GetString("Module", string.Empty) != "BasicProfileModule") + if (config.Configs["Profile"].GetString("Module", string.Empty) != "BasicProfileModule") return; } diff --git a/bin/config-include/Grid.ini b/bin/config-include/Grid.ini index baadbb86ff..52205732f0 100644 --- a/bin/config-include/Grid.ini +++ b/bin/config-include/Grid.ini @@ -27,7 +27,7 @@ SimulationServiceInConnector = true LibraryModule = true -[Profiles] +[Profile] Module = "BasicProfileModule" [SimulationDataStore] diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index 510a315647..b8e66c2733 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -31,7 +31,7 @@ SimulationServiceInConnector = true LibraryModule = true -[Profiles] +[Profile] Module = "BasicProfileModule" [SimulationDataStore] diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini index cfcf5ed8c7..4ff1a269bf 100644 --- a/bin/config-include/Standalone.ini +++ b/bin/config-include/Standalone.ini @@ -22,7 +22,7 @@ LLLoginServiceInConnector = true GridInfoServiceInConnector = true -[Profiles] +[Profile] Module = "BasicProfileModule" [SimulationDataStore] diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index 44ca3acaca..574375eed8 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -32,7 +32,7 @@ AuthenticationServiceInConnector = true SimulationServiceInConnector = true -[Profiles] +[Profile] Module = "BasicProfileModule" [Messaging] From 3fa54a156a83e498a7d5d0949a5f848fe82fe86f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 1 Jun 2011 20:02:26 -0700 Subject: [PATCH 101/186] Changed Friends table to have 165-sized varchars on PrincipalID and FriendID. The reason for this number is the following: there is a combined key of these 2 fields; apparently MySql can't handle keys larger than 1000 bytes; when the table is created with utf8 encoding, this combined key is bigger than 1000 bytes, and the migration fails. WARNING: this is not a new migration! People who have gone through this migration and failed should update the sizes of these fields manually. --- OpenSim/Data/MySQL/Resources/FriendsStore.migrations | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations index 35e5e93cde..5abacf5c87 100644 --- a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations +++ b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations @@ -25,7 +25,8 @@ COMMIT; BEGIN; -ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; +ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(165) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; +ALTER TABLE `Friends` MODIFY COLUMN Friend varchar(165) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; COMMIT; From 43ecc46a224d07661af42379f12f394e1bd873fd Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 1 Jun 2011 20:09:59 -0700 Subject: [PATCH 102/186] It looks like there's a better solution for that problem. Revert "Changed Friends table to have 165-sized varchars on PrincipalID and FriendID. The reason for this number is the following: there is a combined key of these 2 fields; apparently MySql can't handle keys larger than 1000 bytes; when the table is created with utf8 encoding, this combined key is bigger than 1000 bytes, and the migration fails. WARNING: this is not a new migration! People who have gone through this migration and failed should update the sizes of these fields manually." This reverts commit 3fa54a156a83e498a7d5d0949a5f848fe82fe86f. --- OpenSim/Data/MySQL/Resources/FriendsStore.migrations | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations index 5abacf5c87..35e5e93cde 100644 --- a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations +++ b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations @@ -25,8 +25,7 @@ COMMIT; BEGIN; -ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(165) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; -ALTER TABLE `Friends` MODIFY COLUMN Friend varchar(165) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; +ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; COMMIT; From c13acdf5a1a94df9b0ef50b7b2739a9256656582 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 1 Jun 2011 20:19:22 -0700 Subject: [PATCH 103/186] This is the better solution: make the combined key be only on the first 36 characters of each field -- that's the UUIDs. Thanks coyled. WARNING: Again, people who have gone through this migration and failed need to run it manually. --- OpenSim/Data/MySQL/Resources/FriendsStore.migrations | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations index 35e5e93cde..7848e49955 100644 --- a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations +++ b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations @@ -25,7 +25,8 @@ COMMIT; BEGIN; +ALTER TABLE `Friends` DROP PRIMARY KEY; +ALTER TABLE `Friends` ADD PRIMARY KEY(PrincipalID(36), Friend(36)); ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; COMMIT; - From f2f30a78908c93e1397be52e476da9fb5c44282d Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 2 Jun 2011 07:26:40 -0700 Subject: [PATCH 104/186] HG Friends bug fix: connector was shrinking principalID to UUID. --- .../Friends/FriendsServerPostHandler.cs | 19 ++++++++++++--- .../Friends/FriendsServiceConnector.cs | 24 +++++++++---------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs index 9969086a90..fc97d8c221 100644 --- a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs @@ -160,9 +160,9 @@ namespace OpenSim.Server.Handlers.Friends byte[] StoreFriend(Dictionary request) { - FriendInfo friend = new FriendInfo(request); - - bool success = m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, friend.MyFlags); + string principalID = string.Empty, friend = string.Empty; int flags = 0; + FromKeyValuePairs(request, out principalID, out friend, out flags); + bool success = m_FriendsService.StoreFriend(principalID, friend, flags); if (success) return SuccessResult(); @@ -275,6 +275,19 @@ namespace OpenSim.Server.Handlers.Friends return ms.ToArray(); } + void FromKeyValuePairs(Dictionary kvp, out string principalID, out string friend, out int flags) + { + principalID = string.Empty; + if (kvp.ContainsKey("PrincipalID") && kvp["PrincipalID"] != null) + principalID = kvp["PrincipalID"].ToString(); + friend = string.Empty; + if (kvp.ContainsKey("Friend") && kvp["Friend"] != null) + friend = kvp["Friend"].ToString(); + flags = 0; + if (kvp.ContainsKey("MyFlags") && kvp["MyFlags"] != null) + Int32.TryParse(kvp["MyFlags"].ToString(), out flags); + } + #endregion } } diff --git a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs index 08f1dc3133..c5ae0c056e 100644 --- a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs @@ -161,19 +161,8 @@ namespace OpenSim.Services.Connectors.Friends public bool StoreFriend(string PrincipalID, string Friend, int flags) { - FriendInfo finfo = new FriendInfo(); - try - { - finfo.PrincipalID = new UUID(PrincipalID); - } - catch - { - return false; - } - finfo.Friend = Friend; - finfo.MyFlags = flags; - Dictionary sendData = finfo.ToKeyValuePairs(); + Dictionary sendData = ToKeyValuePairs(PrincipalID, Friend, flags); sendData["METHOD"] = "storefriend"; @@ -267,5 +256,16 @@ namespace OpenSim.Services.Connectors.Friends } #endregion + + public Dictionary ToKeyValuePairs(string principalID, string friend, int flags) + { + Dictionary result = new Dictionary(); + result["PrincipalID"] = principalID; + result["Friend"] = friend; + result["MyFlags"] = flags; + + return result; + } + } } \ No newline at end of file From 4696a9c95eaf87e5cb43cdba008d3f41a949d629 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 2 Jun 2011 08:13:54 -0700 Subject: [PATCH 105/186] Bug fix on HG IM. --- .../InstantMessage/HGMessageTransferModule.cs | 8 ++++-- .../HGInstantMessageService.cs | 26 +++++++++---------- .../Services/Interfaces/IHypergridServices.cs | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs index e0c404bba1..4de197e10d 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs @@ -187,12 +187,16 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage // Is the user a local user? UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID); string url = string.Empty; + bool foreigner = false; if (account == null) // foreign user + { url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI"); + foreigner = true; + } Util.FireAndForget(delegate { - bool success = m_IMService.OutgoingInstantMessage(im, url); + bool success = m_IMService.OutgoingInstantMessage(im, url, foreigner); if (!success && account == null) { // One last chance @@ -203,7 +207,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty; if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret)) { - success = m_IMService.OutgoingInstantMessage(im, u); + success = m_IMService.OutgoingInstantMessage(im, u, true); if (success) UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last); } diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index dd5fd71baf..4f68e551d1 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -115,23 +115,23 @@ namespace OpenSim.Services.HypergridService return m_IMSimConnector.SendInstantMessage(im); } else - return TrySendInstantMessage(im, "", true); + return TrySendInstantMessage(im, "", true, false); } - public bool OutgoingInstantMessage(GridInstantMessage im, string url) + public bool OutgoingInstantMessage(GridInstantMessage im, string url, bool foreigner) { m_log.DebugFormat("[HG IM SERVICE]: Sending message from {0} to {1}@{2}", im.fromAgentID, im.toAgentID, url); if (url != string.Empty) - return TrySendInstantMessage(im, url, true); + return TrySendInstantMessage(im, url, true, foreigner); else { PresenceInfo upd = new PresenceInfo(); upd.RegionID = UUID.Zero; - return TrySendInstantMessage(im, upd, true); + return TrySendInstantMessage(im, upd, true, foreigner); } } - protected bool TrySendInstantMessage(GridInstantMessage im, object previousLocation, bool firstTime) + protected bool TrySendInstantMessage(GridInstantMessage im, object previousLocation, bool firstTime, bool foreigner) { UUID toAgentID = new UUID(im.toAgentID); @@ -185,7 +185,7 @@ namespace OpenSim.Services.HypergridService } } - if (upd == null) + if (upd == null && !foreigner) { // 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"); @@ -213,25 +213,25 @@ namespace OpenSim.Services.HypergridService // ok, the user is around somewhere. Let's send back the reply with "success" // even though the IM may still fail. Just don't keep the caller waiting for // the entire time we're trying to deliver the IM - return SendIMToRegion(upd, im, toAgentID); + return SendIMToRegion(upd, im, toAgentID, foreigner); } else if (url != string.Empty) { // ok, the user is around somewhere. Let's send back the reply with "success" // even though the IM may still fail. Just don't keep the caller waiting for // the entire time we're trying to deliver the IM - return ForwardIMToGrid(url, im, toAgentID); + return ForwardIMToGrid(url, im, toAgentID, foreigner); } else if (firstTime && previousLocation is string && (string)previousLocation != string.Empty) { - return ForwardIMToGrid((string)previousLocation, im, toAgentID); + return ForwardIMToGrid((string)previousLocation, im, toAgentID, foreigner); } else m_log.DebugFormat("[HG IM SERVICE]: Unable to locate user {0}", toAgentID); return false; } - bool SendIMToRegion(PresenceInfo upd, GridInstantMessage im, UUID toAgentID) + bool SendIMToRegion(PresenceInfo upd, GridInstantMessage im, UUID toAgentID, bool foreigner) { bool imresult = false; GridRegion reginfo = null; @@ -277,11 +277,11 @@ namespace OpenSim.Services.HypergridService // The version that spawns the thread is SendGridInstantMessageViaXMLRPC // This is recursive!!!!! - return TrySendInstantMessage(im, upd, false); + return TrySendInstantMessage(im, upd, false, foreigner); } } - bool ForwardIMToGrid(string url, GridInstantMessage im, UUID toAgentID) + bool ForwardIMToGrid(string url, GridInstantMessage im, UUID toAgentID, bool foreigner) { if (InstantMessageServiceConnector.SendInstantMessage(url, im)) { @@ -309,7 +309,7 @@ namespace OpenSim.Services.HypergridService // The version that spawns the thread is SendGridInstantMessageViaXMLRPC // This is recursive!!!!! - return TrySendInstantMessage(im, url, false); + return TrySendInstantMessage(im, url, false, foreigner); } } diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs index 753c20523c..82ec8ceee5 100644 --- a/OpenSim/Services/Interfaces/IHypergridServices.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -72,7 +72,7 @@ namespace OpenSim.Services.Interfaces public interface IInstantMessage { bool IncomingInstantMessage(GridInstantMessage im); - bool OutgoingInstantMessage(GridInstantMessage im, string url); + bool OutgoingInstantMessage(GridInstantMessage im, string url, bool foreigner); } public interface IFriendsSimConnector { From 3c15c0b2640b08f3786857837770dcdb53859fd4 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 2 Jun 2011 09:39:09 -0700 Subject: [PATCH 106/186] Added test IM client. --- .../Tests/Clients/InstantMessage/IMClient.cs | 75 +++++++++++++++++++ prebuild.xml | 26 +++++++ 2 files changed, 101 insertions(+) create mode 100644 OpenSim/Tests/Clients/InstantMessage/IMClient.cs diff --git a/OpenSim/Tests/Clients/InstantMessage/IMClient.cs b/OpenSim/Tests/Clients/InstantMessage/IMClient.cs new file mode 100644 index 0000000000..506d17674c --- /dev/null +++ b/OpenSim/Tests/Clients/InstantMessage/IMClient.cs @@ -0,0 +1,75 @@ +/* + * 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.Text; +using System.Reflection; + +using OpenMetaverse; +using log4net; +using log4net.Appender; +using log4net.Layout; + +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.InstantMessage; + +namespace OpenSim.Tests.Clients.InstantMessage +{ + public class IMClient + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + public static void Main(string[] args) + { + ConsoleAppender consoleAppender = new ConsoleAppender(); + consoleAppender.Layout = + new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"); + log4net.Config.BasicConfigurator.Configure(consoleAppender); + + string serverURI = "http://grid.nebadon2025.homeftp.net:8002/"; + GridInstantMessage im = new GridInstantMessage(); + im.fromAgentID = new Guid(); + im.toAgentID = new Guid(); + im.message = "Hello"; + im.imSessionID = new Guid(); + + bool success = InstantMessageServiceConnector.SendInstantMessage(serverURI, im); + + if (success) + m_log.InfoFormat("[IM CLIENT]: Successfully IMed {0}", serverURI); + else + m_log.InfoFormat("[IM CLIENT]: failed to IM {0}", serverURI); + + System.Console.WriteLine("\n"); + } + + } +} diff --git a/prebuild.xml b/prebuild.xml index 1f620dc8b1..0bdd14db43 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2645,6 +2645,32 @@ + + + + ../../../../bin/ + + + + + ../../../../bin/ + + + + ../../../../bin/ + + + + + + + + + + + + + From 65c71050cceb1a823fad682b906e0f8250f244c2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 2 Jun 2011 09:39:29 -0700 Subject: [PATCH 107/186] Extra debug message --- .../Server/Handlers/Hypergrid/InstantMessageServerConnector.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs index 74b742280f..514793d86b 100644 --- a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs @@ -72,6 +72,7 @@ namespace OpenSim.Server.Handlers.Hypergrid if (m_IMService == null) throw new Exception("InstantMessage server connector cannot proceed because of missing service"); + m_log.DebugFormat("[XXX] IM Server Connector is ON"); MainServer.Instance.AddXmlRPCHandler("grid_instant_message", ProcessInstantMessage, false); } From 6312eea459e6c64b6b5fafe06c9b8e6617bb03c3 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 2 Jun 2011 10:14:26 -0700 Subject: [PATCH 108/186] HG IM bug fix: grid_instant_message was being placed in the default port instead of the specified one. --- .../Server/Handlers/Hypergrid/InstantMessageServerConnector.cs | 3 +-- OpenSim/Tests/Clients/InstantMessage/IMClient.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs index 514793d86b..80eb5d2faf 100644 --- a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs @@ -72,8 +72,7 @@ namespace OpenSim.Server.Handlers.Hypergrid if (m_IMService == null) throw new Exception("InstantMessage server connector cannot proceed because of missing service"); - m_log.DebugFormat("[XXX] IM Server Connector is ON"); - MainServer.Instance.AddXmlRPCHandler("grid_instant_message", ProcessInstantMessage, false); + server.AddXmlRPCHandler("grid_instant_message", ProcessInstantMessage, false); } diff --git a/OpenSim/Tests/Clients/InstantMessage/IMClient.cs b/OpenSim/Tests/Clients/InstantMessage/IMClient.cs index 506d17674c..e7304a24dc 100644 --- a/OpenSim/Tests/Clients/InstantMessage/IMClient.cs +++ b/OpenSim/Tests/Clients/InstantMessage/IMClient.cs @@ -54,7 +54,7 @@ namespace OpenSim.Tests.Clients.InstantMessage new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"); log4net.Config.BasicConfigurator.Configure(consoleAppender); - string serverURI = "http://grid.nebadon2025.homeftp.net:8002/"; + string serverURI = "http://127.0.0.1:8002"; GridInstantMessage im = new GridInstantMessage(); im.fromAgentID = new Guid(); im.toAgentID = new Guid(); From 2a12d143c2a3fa996674ee77a34a82100da17230 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 2 Jun 2011 10:44:10 -0700 Subject: [PATCH 109/186] HG IM: increase the timeout value --- .../Connectors/InstantMessage/InstantMessageServiceConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs index 161be02e26..dbce9f613c 100644 --- a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs +++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs @@ -61,7 +61,7 @@ namespace OpenSim.Services.Connectors.InstantMessage try { - XmlRpcResponse GridResp = GridReq.Send(url, 3000); + XmlRpcResponse GridResp = GridReq.Send(url, 10000); Hashtable responseData = (Hashtable)GridResp.Value; From b000d4f67fd31251dfdcabbada371a5f57a80b0a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 2 Jun 2011 21:37:17 +0100 Subject: [PATCH 110/186] minor: add ini.example doc to hint that the server address in [FreeswitchService] must be reachable by viewers --- bin/OpenSim.ini.example | 1 + bin/Robust.HG.ini.example | 1 + bin/Robust.ini.example | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index c5df0dba58..55cf89a0fe 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -649,6 +649,7 @@ ;; !!!!!!!!!!!!!!!!!!!!!!!!!!! ;; The IP address of your FreeSWITCH server. The common case is for this to be the same as the server running the OpenSim standalone ;; This has to be set for the FreeSWITCH service to work + ;; This address must be reachable by viewers. ;ServerAddress = 127.0.0.1 ;; The following configuration parameters are optional diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 0dd93f8bdb..7b2f8acd33 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -107,6 +107,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" ;; The IP address of your FreeSWITCH server. + ;; This address must be reachable by viewers. ; ServerAddress = 127.0.0.1 ;; The following configuration parameters are optional diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index cc018f8867..5d0ec09d7d 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example @@ -21,7 +21,6 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 [Network] port = 8003 - ; HTTPS for "Out of band" management applications such as the remote admin ; module. May specify https_main = True to make the main http server ; use https or "False" to make the main server HTTP @@ -92,6 +91,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" ;; The IP address of your FreeSWITCH server. + ;; This address must be reachable by viewers. ; ServerAddress = 127.0.0.1 ;; The following configuration parameters are optional From dfa4442319397abd91e1ffbf61b02fb63b8f46d2 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 2 Jun 2011 22:43:44 +0100 Subject: [PATCH 111/186] Move the "!!!Standalone Only!!!" [FreeswitchService] section from OpenSim.ini.example to config/StandaloneCommon.ini.example where it belongs. --- bin/OpenSim.ini.example | 40 +------------------ .../StandaloneCommon.ini.example | 36 +++++++++++++++++ 2 files changed, 37 insertions(+), 39 deletions(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 55cf89a0fe..813c5b828c 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -635,51 +635,13 @@ ;; You need to load a local service for a standalone, and a remote service ;; for a grid region. Use one of the lines below, as appropriate - ;; If you're using Freeswitch on a standalone then you will also need to configure the [FreeswitchService] section + ;; If you're using Freeswitch on a standalone then you will also need to configure the [FreeswitchService] section in config-include/StandaloneCommon.ini ; LocalServiceModule = OpenSim.Services.FreeswitchService.dll:FreeswitchService ; LocalServiceModule = OpenSim.Services.Connectors.dll:RemoteFreeswitchConnector ;; If using a remote connector, specify the server URL ; FreeswitchServiceURL = http://my.grid.server:8004/fsapi - -[FreeswitchService] - ;; !!!!!!!!!!!!!!!!!!!!!!!!!!! - ;; !!!!!!STANDALONE ONLY!!!!!! - ;; !!!!!!!!!!!!!!!!!!!!!!!!!!! - ;; The IP address of your FreeSWITCH server. The common case is for this to be the same as the server running the OpenSim standalone - ;; This has to be set for the FreeSWITCH service to work - ;; This address must be reachable by viewers. - ;ServerAddress = 127.0.0.1 - - ;; The following configuration parameters are optional - - ;; By default, this is the same as the ServerAddress - ; Realm = 127.0.0.1 - - ;; By default, this is the same as the ServerAddress on port 5060 - ; SIPProxy = 127.0.0.1:5060 - - ;; Default is 5000ms - ; DefaultTimeout = 5000 - - ;; The dial plan context. Default is "default" - ; Context = default - - ;; Currently unused - ; UserName = freeswitch - - ;; Currently unused - ; Password = password - - ;; The following parameters are for STUN = Simple Traversal of UDP through NATs - ;; See http://wiki.freeswitch.org/wiki/NAT_Traversal - ;; stun.freeswitch.org is not guaranteed to be running so use it in - ;; production at your own risk - ; EchoServer = 127.0.0.1 - ; EchoPort = 50505 - ; AttemptSTUN = false - [Groups] ;# {Enabled} {} {Enable groups?} {true false} false ;; Enables the groups module diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 57380eefa4..aeebcd0658 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -139,6 +139,42 @@ ;AllowedClients = "" ;DeniedClients = "" +[FreeswitchService] + ;; If FreeSWITCH is not being used then you don't need to set any of these parameters + ;; + ;; The IP address of your FreeSWITCH server. The common case is for this to be the same as the server running the OpenSim standalone + ;; This has to be set for the FreeSWITCH service to work + ;; This address must be reachable by viewers. + ;ServerAddress = 127.0.0.1 + + ;; The following configuration parameters are optional + + ;; By default, this is the same as the ServerAddress + ; Realm = 127.0.0.1 + + ;; By default, this is the same as the ServerAddress on port 5060 + ; SIPProxy = 127.0.0.1:5060 + + ;; Default is 5000ms + ; DefaultTimeout = 5000 + + ;; The dial plan context. Default is "default" + ; Context = default + + ;; Currently unused + ; UserName = freeswitch + + ;; Currently unused + ; Password = password + + ;; The following parameters are for STUN = Simple Traversal of UDP through NATs + ;; See http://wiki.freeswitch.org/wiki/NAT_Traversal + ;; stun.freeswitch.org is not guaranteed to be running so use it in + ;; production at your own risk + ; EchoServer = 127.0.0.1 + ; EchoPort = 50505 + ; AttemptSTUN = false + [GridInfoService] ; These settings are used to return information on a get_grid_info call. ; Client launcher scripts and third-party clients make use of this to From 76c60f1f99ca8aa7c1a336918aa0ef5f83b1ae04 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 3 Jun 2011 08:27:01 -0700 Subject: [PATCH 112/186] Moved CreateNewInventoryItem to the InventoryAccessModule in preparation for supporting HG landmarks. --- .../InventoryAccess/InventoryAccessModule.cs | 79 ++++++++++++++++++- .../Framework/Scenes/Scene.Inventory.cs | 74 +---------------- OpenSim/Region/Framework/Scenes/Scene.cs | 4 +- 3 files changed, 81 insertions(+), 76 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 1370b1fe8e..641a0425c6 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.Net; using System.Xml; using System.Reflection; +using System.Text; using System.Threading; using OpenSim.Framework; @@ -128,7 +129,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess protected virtual void OnNewClient(IClientAPI client) { - + client.OnCreateNewInventoryItem += CreateNewInventoryItem; } public virtual void Close() @@ -156,6 +157,82 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #region Inventory Access + /// + /// Create a new inventory item. Called when the client creates a new item directly within their + /// inventory (e.g. by selecting a context inventory menu option). + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte assetType, + byte wearableType, uint nextOwnerMask, int creationDate) + { + m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID); + + if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) + return; + + InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId); + InventoryFolderBase folder = m_Scene.InventoryService.GetFolder(f); + + if (folder == null || folder.Owner != remoteClient.AgentId) + return; + + if (transactionID == UUID.Zero) + { + ScenePresence presence; + if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence)) + { + byte[] data = null; + + if (invType == (sbyte)InventoryType.Landmark && presence != null) + { + string strdata = GenerateLandmark(presence); + data = Encoding.ASCII.GetBytes(strdata); + } + + AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); + m_Scene.AssetService.Store(asset); + + m_Scene.CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate); + } + else + { + m_log.ErrorFormat( + "ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", + remoteClient.AgentId); + } + } + else + { + IAgentAssetTransactions agentTransactions = m_Scene.RequestModuleInterface(); + if (agentTransactions != null) + { + agentTransactions.HandleItemCreationFromTransaction( + remoteClient, transactionID, folderID, callbackID, description, + name, invType, assetType, wearableType, nextOwnerMask); + } + } + } + + protected virtual string GenerateLandmark(ScenePresence presence) + { + Vector3 pos = presence.AbsolutePosition; + return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n", + presence.Scene.RegionInfo.RegionID, + pos.X, pos.Y, pos.Z, + presence.RegionHandle); + } + /// /// Capability originating call to update the asset of an item in an agent's inventory /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 3c4787397b..b70e1c3a56 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -778,7 +778,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - private void CreateNewInventoryItem(IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, + public void CreateNewInventoryItem(IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) { CreateNewInventoryItem( @@ -832,78 +832,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Create a new inventory item. Called when the client creates a new item directly within their - /// inventory (e.g. by selecting a context inventory menu option). - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, - uint callbackID, string description, string name, sbyte invType, - sbyte assetType, - byte wearableType, uint nextOwnerMask, int creationDate) - { - m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID); - - if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) - return; - - InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId); - InventoryFolderBase folder = InventoryService.GetFolder(f); - - if (folder == null || folder.Owner != remoteClient.AgentId) - return; - - if (transactionID == UUID.Zero) - { - ScenePresence presence; - if (TryGetScenePresence(remoteClient.AgentId, out presence)) - { - byte[] data = null; - - if (invType == (sbyte)InventoryType.Landmark && presence != null) - { - Vector3 pos = presence.AbsolutePosition; - string strdata = String.Format( - "Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n", - presence.Scene.RegionInfo.RegionID, - pos.X, pos.Y, pos.Z, - presence.RegionHandle); - data = Encoding.ASCII.GetBytes(strdata); - } - - AssetBase asset = CreateAsset(name, description, assetType, data, remoteClient.AgentId); - AssetService.Store(asset); - - CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate); - } - else - { - m_log.ErrorFormat( - "ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", - remoteClient.AgentId); - } - } - else - { - IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); - if (agentTransactions != null) - { - agentTransactions.HandleItemCreationFromTransaction( - remoteClient, transactionID, folderID, callbackID, description, - name, invType, assetType, wearableType, nextOwnerMask); - } - } - } - /// /// Link an inventory item to an existing item. /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 1d562fdb45..b17968352b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2726,7 +2726,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientInventoryEvents(IClientAPI client) { - client.OnCreateNewInventoryItem += CreateNewInventoryItem; + client.OnLinkInventoryItem += HandleLinkInventoryItem; client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; @@ -2853,7 +2853,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client) { - client.OnCreateNewInventoryItem -= CreateNewInventoryItem; + client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder; client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder; client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!! From 995b893e4c7c89db8fc044e3f8524229490fb220 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 3 Jun 2011 09:04:34 -0700 Subject: [PATCH 113/186] HG Landmarks being created. WARNING: new config var under [HGInventoryAccessModule], Gatekeeper. --- .../InventoryAccess/HGInventoryAccessModule.cs | 15 +++++++++++++++ .../InventoryAccess/InventoryAccessModule.cs | 7 +++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 429dda7313..844054c808 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess private string m_ProfileServerURI; private bool m_OutboundPermission; + private string m_ThisGatekeeper; // private bool m_Initialized = false; @@ -85,6 +86,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { m_ProfileServerURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty); m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); + m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); } else m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); @@ -119,6 +121,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #endregion #region Overrides of Basic Inventory Access methods + + protected override string GenerateLandmark(ScenePresence presence, out string suffix) + { + suffix = " @ " + m_ThisGatekeeper; + Vector3 pos = presence.AbsolutePosition; + return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\ngatekeeper {5}", + presence.Scene.RegionInfo.RegionID, + pos.X, pos.Y, pos.Z, + presence.RegionHandle, + m_ThisGatekeeper); + } + + /// /// CapsUpdateInventoryItemAsset /// diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 641a0425c6..d441aa46ba 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -196,8 +196,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (invType == (sbyte)InventoryType.Landmark && presence != null) { - string strdata = GenerateLandmark(presence); + string suffix = string.Empty; + string strdata = GenerateLandmark(presence, out suffix); data = Encoding.ASCII.GetBytes(strdata); + description += suffix; } AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); @@ -224,8 +226,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } - protected virtual string GenerateLandmark(ScenePresence presence) + protected virtual string GenerateLandmark(ScenePresence presence, out string suffix) { + suffix = string.Empty; Vector3 pos = presence.AbsolutePosition; return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n", presence.Scene.RegionInfo.RegionID, From e33cedfd427779a3df844150869eb07b664849df Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 3 Jun 2011 10:26:58 -0700 Subject: [PATCH 114/186] HG Landmarks now working. --- OpenSim/Framework/AssetLandmark.cs | 3 ++ OpenSim/Framework/IClientAPI.cs | 2 +- .../ClientStack/Linden/UDP/LLClientView.cs | 5 +- .../EntityTransfer/EntityTransferModule.cs | 29 +++++++++- .../EntityTransfer/HGEntityTransferModule.cs | 53 +++++++++++++++++++ .../HGInventoryAccessModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 23 +------- 7 files changed, 89 insertions(+), 28 deletions(-) diff --git a/OpenSim/Framework/AssetLandmark.cs b/OpenSim/Framework/AssetLandmark.cs index f433235ec8..103f75676c 100644 --- a/OpenSim/Framework/AssetLandmark.cs +++ b/OpenSim/Framework/AssetLandmark.cs @@ -35,6 +35,7 @@ namespace OpenSim.Framework public Vector3 Position; public ulong RegionHandle; public UUID RegionID; + public string Gatekeeper = string.Empty; public int Version; public AssetLandmark(AssetBase a) @@ -51,6 +52,8 @@ namespace OpenSim.Framework string[] parts = temp.Split('\n'); int.TryParse(parts[0].Substring(17, 1), out Version); UUID.TryParse(parts[1].Substring(10, 36), out RegionID); + if (parts.Length >= 5) + Gatekeeper = parts[4].Replace("gatekeeper ", ""); // The position is a vector with spaces as separators ("10.3 32.5 43"). // Parse each scalar separately to take into account the system's culture setting. string[] scalars = parts[2].Substring(10, parts[2].Length - 10).Split(' '); diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 137f432624..659d42ff91 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -83,7 +83,7 @@ namespace OpenSim.Framework IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags); public delegate void TeleportLandmarkRequest( - IClientAPI remoteClient, UUID regionID, Vector3 position); + IClientAPI remoteClient, AssetLandmark lm); public delegate void DisconnectUser(); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index d8fcb6223d..3a9e4b7682 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -8301,6 +8301,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AssetLandmark lm; if (lmid != UUID.Zero) { + //AssetBase lma = m_assetCache.GetAsset(lmid, false); AssetBase lma = m_assetService.Get(lmid.ToString()); @@ -8341,13 +8342,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP TeleportLandmarkRequest handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; if (handlerTeleportLandmarkRequest != null) { - handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position); + handlerTeleportLandmarkRequest(this, lm); } else { //no event handler so cancel request - - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); tpCancel.Info.AgentID = tpReq.Info.AgentID; tpCancel.Info.SessionID = tpReq.Info.SessionID; diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index ec084fbaf2..1341533167 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected bool m_Enabled = false; protected Scene m_aScene; + protected List m_Scenes = new List(); protected List m_agentsInTransit; private ExpiringCache> m_bannedRegions = new ExpiringCache>(); @@ -96,6 +97,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (m_aScene == null) m_aScene = scene; + m_Scenes.Add(scene); scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += OnNewClient; } @@ -103,6 +105,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void OnNewClient(IClientAPI client) { client.OnTeleportHomeRequest += TeleportHome; + client.OnTeleportLandmarkRequest += RequestTeleportLandmark; } public virtual void Close() @@ -118,6 +121,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; if (scene == m_aScene) m_aScene = null; + + m_Scenes.Remove(scene); } public virtual void RegionLoaded(Scene scene) @@ -127,7 +132,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } - #endregion #region Agent Teleports @@ -556,6 +560,29 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #endregion + #region Landmark Teleport + /// + /// Tries to teleport agent to landmark. + /// + /// + /// + /// + public virtual void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm) + { + GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID); + + if (info == null) + { + // can't find the region: Tell viewer and abort + remoteClient.SendTeleportFailed("The teleport destination could not be found."); + return; + } + ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position, + Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark)); + } + + #endregion + #region Teleport Home public virtual void TeleportHome(UUID id, IClientAPI client) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 5c53f787bf..f6ec481626 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -87,6 +87,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected override void OnNewClient(IClientAPI client) { client.OnTeleportHomeRequest += TeleportHome; + client.OnTeleportLandmarkRequest += RequestTeleportLandmark; client.OnConnectionClosed += new Action(OnConnectionClosed); } @@ -228,6 +229,58 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq); } + + /// + /// Tries to teleport agent to landmark. + /// + /// + /// + /// + public override void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm) + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}", + (lm.Gatekeeper == string.Empty ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position); + if (lm.Gatekeeper == string.Empty) + { + base.RequestTeleportLandmark(remoteClient, lm); + return; + } + + GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID); + + // Local region? + if (info != null) + { + ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position, + Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark)); + return; + } + else + { + // Foreign region + Scene scene = (Scene)(remoteClient.Scene); + GatekeeperServiceConnector gConn = new GatekeeperServiceConnector(); + GridRegion gatekeeper = new GridRegion(); + gatekeeper.ServerURI = lm.Gatekeeper; + GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(lm.RegionID)); + if (finalDestination != null) + { + ScenePresence sp = scene.GetScenePresence(remoteClient.AgentId); + IEntityTransferModule transferMod = scene.RequestModuleInterface(); + IEventQueue eq = sp.Scene.RequestModuleInterface(); + if (transferMod != null && sp != null && eq != null) + transferMod.DoTeleport(sp, gatekeeper, finalDestination, lm.Position, + Vector3.UnitX, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark), eq); + } + + } + + // can't find the region: Tell viewer and abort + remoteClient.SendTeleportFailed("The teleport destination could not be found."); + + } + + #endregion #region IUserAgentVerificationModule diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 844054c808..7964b4fd2d 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -126,7 +126,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { suffix = " @ " + m_ThisGatekeeper; Vector3 pos = presence.AbsolutePosition; - return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\ngatekeeper {5}", + return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\ngatekeeper {5}\n", presence.Scene.RegionInfo.RegionID, pos.X, pos.Y, pos.Z, presence.RegionHandle, diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b17968352b..77301d8844 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2749,7 +2749,6 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientTeleportEvents(IClientAPI client) { client.OnTeleportLocationRequest += RequestTeleportLocation; - client.OnTeleportLandmarkRequest += RequestTeleportLandmark; } public virtual void SubscribeToClientScriptEvents(IClientAPI client) @@ -2875,7 +2874,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientTeleportEvents(IClientAPI client) { client.OnTeleportLocationRequest -= RequestTeleportLocation; - client.OnTeleportLandmarkRequest -= RequestTeleportLandmark; + //client.OnTeleportLandmarkRequest -= RequestTeleportLandmark; //client.OnTeleportHomeRequest -= TeleportClientHome; } @@ -3925,26 +3924,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Tries to teleport agent to landmark. - /// - /// - /// - /// - public void RequestTeleportLandmark(IClientAPI remoteClient, UUID regionID, Vector3 position) - { - GridRegion info = GridService.GetRegionByUUID(UUID.Zero, regionID); - - if (info == null) - { - // can't find the region: Tell viewer and abort - remoteClient.SendTeleportFailed("The teleport destination could not be found."); - return; - } - - RequestTeleportLocation(remoteClient, info.RegionHandle, position, Vector3.Zero, (uint)(TPFlags.SetLastToTarget | TPFlags.ViaLandmark)); - } - public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) { if (m_teleportModule != null) From 7772640ae8041555c1f1098ed036c1c42944a108 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 3 Jun 2011 10:29:59 -0700 Subject: [PATCH 115/186] .ini.example's updated for HG Landmarks --- bin/config-include/GridCommon.ini.example | 3 ++- bin/config-include/StandaloneCommon.ini.example | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index c5c26ec8bd..e2e6459c58 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -100,10 +100,11 @@ [HGInventoryAccessModule] ; ; === HG ONLY === - ; Change this to your profile server + ; Change this to your server ; accessible from other grids ; ProfileServerURI = "http://mygridserver.com:8002/user" + Gatekeeper = "http://mygridserver.com:8002" ;; If you want to protect your assets from being copied by foreign visitors ;; uncomment the next line. You may want to do this on sims that have licensed content. ; OutboundPermission = False diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 57380eefa4..cda3ff86ea 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -36,6 +36,7 @@ [HGInventoryAccessModule] ProfileServerURI = "http://127.0.0.1:9000/profiles" + Gatekeeper = "http://127.0.0.1:9000" ;; If you want to protect your assets from being copied by foreign visitors ;; uncomment the next line. You may want to do this on sims that have licensed content. From fde3e704d3c6833da0a1ab80cc50549ad9581cd0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 3 Jun 2011 10:50:55 -0700 Subject: [PATCH 116/186] oops --- .../Framework/EntityTransfer/HGEntityTransferModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index f6ec481626..37d81a311f 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -239,7 +239,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer public override void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm) { m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}", - (lm.Gatekeeper == string.Empty ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position); + (lm.Gatekeeper == string.Empty) ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position); if (lm.Gatekeeper == string.Empty) { base.RequestTeleportLandmark(remoteClient, lm); From 623706d988d47c3c0f3d46b68e77f9c54038d3f5 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 3 Jun 2011 11:33:44 -0700 Subject: [PATCH 117/186] HG Landmarks bug fix: pull landmark asset data from user's asset server when user is traveling. --- .../ClientStack/Linden/UDP/LLClientView.cs | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3a9e4b7682..cefceb0beb 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -8308,10 +8308,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (lma == null) { // Failed to find landmark - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpReq.Info.SessionID; - tpCancel.Info.AgentID = tpReq.Info.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); + + // Let's try to search in the user's home asset server + lma = FindAssetInUserAssetServer(lmid.ToString()); + + if (lma == null) + { + // Really doesn't exist + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpReq.Info.SessionID; + tpCancel.Info.AgentID = tpReq.Info.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } } try @@ -8356,6 +8364,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + private AssetBase FindAssetInUserAssetServer(string id) + { + AgentCircuitData aCircuit = ((Scene)Scene).AuthenticateHandler.GetAgentCircuitData(CircuitCode); + if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) + { + string assetServer = aCircuit.ServiceURLs["AssetServerURI"].ToString(); + return ((Scene)Scene).AssetService.Get(assetServer + "/" + id); + } + + return null; + } + private bool HandleTeleportLocationRequest(IClientAPI sender, Packet Pack) { TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; From cf86ba5559c7158af5c84415f78d5524b4191292 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 3 Jun 2011 11:48:24 -0700 Subject: [PATCH 118/186] Added prefix HG to the name of the landmark item in inventory, as a soft reminder that the landmark belongs to a place in another grid. People can change the name, but that's their decision. --- .../Framework/InventoryAccess/HGInventoryAccessModule.cs | 7 ++++++- .../Framework/InventoryAccess/InventoryAccessModule.cs | 8 +++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 7964b4fd2d..49d484b0e8 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -122,8 +122,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #region Overrides of Basic Inventory Access methods - protected override string GenerateLandmark(ScenePresence presence, out string suffix) + protected override string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix) { + UserAccount account = m_Scene.UserAccountService.GetUserAccount(m_Scene.RegionInfo.ScopeID, presence.UUID); + if (account == null) + prefix = "HG "; + else + prefix = string.Empty; suffix = " @ " + m_ThisGatekeeper; Vector3 pos = presence.AbsolutePosition; return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\ngatekeeper {5}\n", diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index d441aa46ba..29303030a3 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -196,9 +196,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (invType == (sbyte)InventoryType.Landmark && presence != null) { - string suffix = string.Empty; - string strdata = GenerateLandmark(presence, out suffix); + string suffix = string.Empty, prefix = string.Empty; + string strdata = GenerateLandmark(presence, out prefix, out suffix); data = Encoding.ASCII.GetBytes(strdata); + name = prefix + name; description += suffix; } @@ -226,8 +227,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } - protected virtual string GenerateLandmark(ScenePresence presence, out string suffix) + protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix) { + prefix = string.Empty; suffix = string.Empty; Vector3 pos = presence.AbsolutePosition; return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n", From 527e10a04e9108bebe5de76541d47409dd6ce4f4 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 3 Jun 2011 23:13:05 +0100 Subject: [PATCH 119/186] add stub UserInventoryTests.GiveInventoryFolder(). Not yet complete --- .../Scenes/Tests/UserInventoryTests.cs | 70 +++++++++++++++++++ .../Common/Helpers/UserInventoryHelpers.cs | 11 ++- 2 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs new file mode 100644 index 0000000000..b82ddb4065 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -0,0 +1,70 @@ +/* + * 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 System.Text; +using System.Threading; +using System.Timers; +using Timer=System.Timers.Timer; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenMetaverse.Assets; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; +using OpenSim.Services.Interfaces; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.Framework.Tests +{ + [TestFixture] + public class UserInventoryTests + { + [Test] + public void TestGiveInventoryFolder() + { + Scene scene = SceneSetupHelpers.SetupScene(); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); + UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene); + InventoryFolderBase folder1 + = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, "folder1"); + + scene.GiveInventoryFolder(user2.PrincipalID, user1.PrincipalID, folder1.ID, UUID.Zero); + +// InventoryFolderBase receivedFolder1Template = new InventoryFolderBase( +// InventoryFolderBase receivedFolder1 = scene.InventoryService.GetFolder + } + } +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs index 04191349e3..e33145fc7a 100644 --- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs @@ -40,8 +40,15 @@ namespace OpenSim.Tests.Common { public static readonly string PATH_DELIMITER = "/"; - public static InventoryItemBase CreateInventoryItem( - Scene scene, string itemName, UUID itemId, string folderPath, UUID userId) + /// + /// Creates a notecard in the objects folder. + /// + /// + /// + /// + /// + /// + public static InventoryItemBase CreateInventoryItem(Scene scene, string itemName, UUID itemId, UUID userId) { InventoryItemBase item = new InventoryItemBase(); item.Name = itemName; From d09210da869ad2a91c9578225a1ca4843d565e05 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 3 Jun 2011 23:15:31 +0100 Subject: [PATCH 120/186] minor: add in method print out to new test --- OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index b82ddb4065..651df3ea0d 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -55,6 +55,9 @@ namespace OpenSim.Region.Framework.Tests [Test] public void TestGiveInventoryFolder() { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + Scene scene = SceneSetupHelpers.SetupScene(); UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene); From 66004a9375bdb736b4e2569f2791ac14ed4925e4 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 3 Jun 2011 23:43:09 +0100 Subject: [PATCH 121/186] If an llSensor() is in an attachment, make the detection cone face in the direction of the avatar, not the relative rotation of the attachment towards the avatar. This is effectively a copy/paste from 459323a, which should be refactored sometime. This seems the obvious problem from field reports but I have not tested the fix myself. Feedback welcome. --- .../Shared/Api/Implementation/Plugins/SensorRepeat.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 47c7915a3e..e53a61ad47 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -308,7 +308,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins // In attachments, the sensor cone always orients with the // avatar rotation. This may include a nonzero elevation if // in mouselook. - ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar); q = avatar.Rotation; } @@ -422,7 +421,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins SceneObjectPart SensePoint = ts.host; Vector3 fromRegionPos = SensePoint.AbsolutePosition; + Quaternion q = SensePoint.RotationOffset; + if (SensePoint.ParentGroup.RootPart.IsAttachment) + { + // In attachments, the sensor cone always orients with the + // avatar rotation. This may include a nonzero elevation if + // in mouselook. + ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar); + q = avatar.Rotation; + } + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); From 1543fd7fff3b3f3a7ce07caa3ed19846b6587df7 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 4 Jun 2011 00:20:54 +0100 Subject: [PATCH 122/186] extend TestGiveInventoryFolder() to check for the receipt by user 2 --- .../Scenes/Tests/UserInventoryTests.cs | 6 ++++-- .../Common/Helpers/UserInventoryHelpers.cs | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index 651df3ea0d..c6bd296bb9 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -66,8 +66,10 @@ namespace OpenSim.Region.Framework.Tests scene.GiveInventoryFolder(user2.PrincipalID, user1.PrincipalID, folder1.ID, UUID.Zero); -// InventoryFolderBase receivedFolder1Template = new InventoryFolderBase( -// InventoryFolderBase receivedFolder1 = scene.InventoryService.GetFolder + InventoryFolderBase retrievedFolder1 + = UserInventoryHelpers.GetInventoryFolder(scene.InventoryService, user2.PrincipalID, "folder1"); + + Assert.That(retrievedFolder1, Is.Not.Null); } } } \ No newline at end of file diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs index e33145fc7a..03215f25d1 100644 --- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs @@ -26,8 +26,10 @@ */ using System; +using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; @@ -118,5 +120,24 @@ namespace OpenSim.Tests.Common else return newFolder; } + + /// + /// Get the inventory folder that matches the path name. If there are multiple folders then only the first + /// is returned. + /// + /// + /// + /// + /// null if no folder matching the path was found + public static InventoryFolderBase GetInventoryFolder(IInventoryService inventoryService, UUID userId, string path) + { + List folders + = InventoryArchiveUtils.FindFolderByPath(inventoryService, userId, path); + + if (folders.Count != 0) + return folders[0]; + else + return null; + } } } \ No newline at end of file From 896f039513398a46458b18ef49f52a9a3ac43659 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 4 Jun 2011 00:51:49 +0100 Subject: [PATCH 123/186] create TestGetInventoryItem() --- .../Archiver/InventoryArchiveUtils.cs | 20 +++++-------- .../Scenes/Tests/UserInventoryTests.cs | 19 +++++++++++++ .../Common/Helpers/UserInventoryHelpers.cs | 28 ++++++++++++++++++- 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs index 47e34dcdd6..dc665c1dc0 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs @@ -181,25 +181,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// Find an item given a PATH_DELIMITOR delimited path starting from this folder. - /// - /// This method does not handle paths that contain multiple delimitors + /// + /// + /// This method does not handle paths that contain multiple delimiters /// /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some /// XPath like expression /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. - /// + /// /// - /// - /// Inventory service to query - /// - /// - /// The folder from which the path starts - /// - /// - /// - /// The path to the required item. - /// + /// Inventory service to query + /// The folder from which the path starts + /// The path to the required item. /// null if the item is not found public static InventoryItemBase FindItemByPath( IInventoryService inventoryService, InventoryFolderBase startFolder, string path) diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index c6bd296bb9..bacf7c1889 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -52,6 +52,25 @@ namespace OpenSim.Region.Framework.Tests [TestFixture] public class UserInventoryTests { + [Test] + public void TestGiveInventoryItem() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene(); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); + UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene); + InventoryItemBase item1 = UserInventoryHelpers.CreateInventoryItem(scene, "item1", user1.PrincipalID); + + scene.GiveInventoryItem(user2.PrincipalID, user1.PrincipalID, item1.ID); + + InventoryItemBase retrievedItem1 + = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, user2.PrincipalID, "Objects/item1"); + + Assert.That(retrievedItem1, Is.Not.Null); + } + [Test] public void TestGiveInventoryFolder() { diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs index 03215f25d1..93b655a42b 100644 --- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs @@ -43,7 +43,20 @@ namespace OpenSim.Tests.Common public static readonly string PATH_DELIMITER = "/"; /// - /// Creates a notecard in the objects folder. + /// Creates a notecard in the objects folder and specify an item id. + /// + /// + /// + /// + /// + /// + public static InventoryItemBase CreateInventoryItem(Scene scene, string itemName, UUID userId) + { + return CreateInventoryItem(scene, itemName, UUID.Random(), userId); + } + + /// + /// Creates a notecard in the objects folder and specify an item id. /// /// /// @@ -139,5 +152,18 @@ namespace OpenSim.Tests.Common else return null; } + + /// + /// Get the inventory item that matches the path name. If there are multiple items then only the first + /// is returned. + /// + /// + /// + /// + /// null if no item matching the path was found + public static InventoryItemBase GetInventoryItem(IInventoryService inventoryService, UUID userId, string path) + { + return InventoryArchiveUtils.FindItemByPath(inventoryService, userId, path); + } } } \ No newline at end of file From fe890554fbf47cafda2a41e04b400d971f1242ad Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 4 Jun 2011 01:37:01 +0100 Subject: [PATCH 124/186] insert an InventoryArchiveUtils.FindItemsByPath() to return multiple items rather than just the first one --- .../Archiver/InventoryArchiveUtils.cs | 47 +++++++++++++++---- .../Archiver/InventoryArchiveWriteRequest.cs | 3 -- .../Scenes/Tests/UserInventoryTests.cs | 3 ++ 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs index dc665c1dc0..e7fb43a3a5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs @@ -149,14 +149,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// Find an item given a PATH_DELIMITOR delimited path starting from the user's root folder. - /// + /// + /// /// This method does not handle paths that contain multiple delimitors /// /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some /// XPath like expression /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. - /// + /// /// /// /// Inventory service to query @@ -178,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return FindItemByPath(inventoryService, rootFolder, path); } - + /// /// Find an item given a PATH_DELIMITOR delimited path starting from this folder. /// @@ -190,14 +191,43 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. /// + /// + /// Inventory service to query + /// The folder from which the path starts + /// The path to the required item. + /// null if the item is not found + public static InventoryItemBase FindItemByPath( + IInventoryService inventoryService, InventoryFolderBase startFolder, string path) + { + List foundItems = FindItemsByPath(inventoryService, startFolder, path); + + if (foundItems.Count != 0) + return foundItems[0]; + else + return null; + } + + /// + /// Find items that match a given PATH_DELIMITOR delimited path starting from this folder. + /// + /// + /// This method does not handle paths that contain multiple delimiters + /// + /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some + /// XPath like expression + /// + /// FIXME: Delimitors which occur in names themselves are not currently escapable. + /// /// /// Inventory service to query /// The folder from which the path starts /// The path to the required item. - /// null if the item is not found - public static InventoryItemBase FindItemByPath( + /// The items that were found with this path. An empty list if no items were found. + public static List FindItemsByPath( IInventoryService inventoryService, InventoryFolderBase startFolder, string path) { + List foundItems = new List(); + // If the path isn't just / then trim any starting extraneous slashes path = path.TrimStart(new char[] { PATH_DELIMITER }); @@ -221,7 +251,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID); if (item.Name == components[0]) - return item; + foundItems.Add(item); } } else @@ -233,12 +263,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver foreach (InventoryFolderBase folder in contents.Folders) { if (folder.Name == components[0]) - return FindItemByPath(inventoryService, folder, components[1]); + foundItems.AddRange(FindItemsByPath(inventoryService, folder, components[1])); } } - // We didn't find an item or intermediate folder with the given name - return null; + return foundItems; } /// diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index c34a0ecf90..c2ad079536 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -255,10 +255,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // The path may point to an item instead if (inventoryFolder == null) - { inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); - //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath); - } if (null == inventoryFolder && null == inventoryItem) { diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index bacf7c1889..83f0686636 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -69,6 +69,9 @@ namespace OpenSim.Region.Framework.Tests = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, user2.PrincipalID, "Objects/item1"); Assert.That(retrievedItem1, Is.Not.Null); + + // Try giving back the freshly received item + //scene.GiveInventoryItem(user1.PrincipalID, user2.PrincipalID, retrievedItem1.ID); } [Test] From 12b1cbf8bfc559e4da40abf518e8e99fac793870 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 4 Jun 2011 02:39:26 +0100 Subject: [PATCH 125/186] Fix give inventory tests to use different users rather than (accidentally) the same user. Extend TestGiveInventoryItem() to test giving back the same item. --- .../Archiver/InventoryArchiveUtils.cs | 19 +- .../Framework/Scenes/Scene.Inventory.cs | 370 +++++++++--------- .../Scenes/Tests/UserInventoryTests.cs | 17 +- .../InventoryService/InventoryService.cs | 8 +- .../Common/Helpers/UserAccountHelpers.cs | 11 +- .../Common/Helpers/UserInventoryHelpers.cs | 25 +- 6 files changed, 247 insertions(+), 203 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs index e7fb43a3a5..0d90a158c3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs @@ -206,7 +206,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver else return null; } - + + public static List FindItemsByPath( + IInventoryService inventoryService, UUID userId, string path) + { + InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); + + if (null == rootFolder) + return new List(); + + return FindItemsByPath(inventoryService, rootFolder, path); + } + /// /// Find items that match a given PATH_DELIMITOR delimited path starting from this folder. /// @@ -239,11 +250,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (components.Length == 1) { // m_log.DebugFormat( -// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", +// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", // components[0], startFolder.Name, startFolder.ID); List items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); - + // m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count); foreach (InventoryItemBase item in items) @@ -257,7 +268,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver else { // m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]); - + InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); foreach (InventoryFolderBase folder in contents.Folders) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index b70e1c3a56..f37f94ad32 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -425,192 +425,198 @@ namespace OpenSim.Region.Framework.Scenes InventoryItemBase item = new InventoryItemBase(itemId, senderId); item = InventoryService.GetItem(item); - if ((item != null) && (item.Owner == senderId)) + if (item == null) { - IUserManagement uman = RequestModuleInterface(); - if (uman != null) - uman.AddUser(item.CreatorIdAsUuid, item.CreatorData); - - if (!Permissions.BypassPermissions()) - { - if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) - return null; - } - - // Insert a copy of the item into the recipient - InventoryItemBase itemCopy = new InventoryItemBase(); - itemCopy.Owner = recipient; - itemCopy.CreatorId = item.CreatorId; - itemCopy.CreatorData = item.CreatorData; - itemCopy.ID = UUID.Random(); - itemCopy.AssetID = item.AssetID; - itemCopy.Description = item.Description; - itemCopy.Name = item.Name; - itemCopy.AssetType = item.AssetType; - itemCopy.InvType = item.InvType; - itemCopy.Folder = recipientFolderId; - - if (Permissions.PropagatePermissions() && recipient != senderId) - { - // Trying to do this right this time. This is evil. If - // you believe in Good, go elsewhere. Vampires and other - // evil creatores only beyond this point. You have been - // warned. - - // We're going to mask a lot of things by the next perms - // Tweak the next perms to be nicer to our data - // - // In this mask, all the bits we do NOT want to mess - // with are set. These are: - // - // Transfer - // Copy - // Modufy - uint permsMask = ~ ((uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer | - (uint)PermissionMask.Modify); - - // Now, reduce the next perms to the mask bits - // relevant to the operation - uint nextPerms = permsMask | (item.NextPermissions & - ((uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer | - (uint)PermissionMask.Modify)); - - // nextPerms now has all bits set, except for the actual - // next permission bits. - - // This checks for no mod, no copy, no trans. - // This indicates an error or messed up item. Do it like - // SL and assume trans - if (nextPerms == permsMask) - nextPerms |= (uint)PermissionMask.Transfer; - - // Inventory owner perms are the logical AND of the - // folded perms and the root prim perms, however, if - // the root prim is mod, the inventory perms will be - // mod. This happens on "take" and is of little concern - // here, save for preventing escalation - - // This hack ensures that items previously permalocked - // get unlocked when they're passed or rezzed - uint basePerms = item.BasePermissions | - (uint)PermissionMask.Move; - uint ownerPerms = item.CurrentPermissions; - - // If this is an object, root prim perms may be more - // permissive than folded perms. Use folded perms as - // a mask - if (item.InvType == (int)InventoryType.Object) - { - // Create a safe mask for the current perms - uint foldedPerms = (item.CurrentPermissions & 7) << 13; - foldedPerms |= permsMask; - - bool isRootMod = (item.CurrentPermissions & - (uint)PermissionMask.Modify) != 0 ? - true : false; - - // Mask the owner perms to the folded perms - ownerPerms &= foldedPerms; - basePerms &= foldedPerms; - - // If the root was mod, let the mask reflect that - // We also need to adjust the base here, because - // we should be able to edit in-inventory perms - // for the root prim, if it's mod. - if (isRootMod) - { - ownerPerms |= (uint)PermissionMask.Modify; - basePerms |= (uint)PermissionMask.Modify; - } - } - - // These will be applied to the root prim at next rez. - // The slam bit (bit 3) and folded permission (bits 0-2) - // are preserved due to the above mangling - ownerPerms &= nextPerms; - - // Mask the base permissions. This is a conservative - // approach altering only the three main perms - basePerms &= nextPerms; - - // Assign to the actual item. Make sure the slam bit is - // set, if it wasn't set before. - itemCopy.BasePermissions = basePerms; - itemCopy.CurrentPermissions = ownerPerms; - itemCopy.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; - - itemCopy.NextPermissions = item.NextPermissions; - - // This preserves "everyone can move" - itemCopy.EveryOnePermissions = item.EveryOnePermissions & - nextPerms; - - // Intentionally killing "share with group" here, as - // the recipient will not have the group this is - // set to - itemCopy.GroupPermissions = 0; - } - else - { - itemCopy.CurrentPermissions = item.CurrentPermissions; - itemCopy.NextPermissions = item.NextPermissions; - itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions; - itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; - itemCopy.BasePermissions = item.BasePermissions; - } - - if (itemCopy.Folder == UUID.Zero) - { - InventoryFolderBase folder = InventoryService.GetFolderForType(recipient, (AssetType)itemCopy.AssetType); - - if (folder != null) - { - itemCopy.Folder = folder.ID; - } - else - { - InventoryFolderBase root = InventoryService.GetRootFolder(recipient); - - if (root != null) - itemCopy.Folder = root.ID; - else - return null; // No destination - } - } - - itemCopy.GroupID = UUID.Zero; - itemCopy.GroupOwned = false; - itemCopy.Flags = item.Flags; - itemCopy.SalePrice = item.SalePrice; - itemCopy.SaleType = item.SaleType; - - if (AddInventoryItem(itemCopy)) - { - IInventoryAccessModule invAccess = RequestModuleInterface(); - if (invAccess != null) - invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); - } - - if (!Permissions.BypassPermissions()) - { - if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - { - List items = new List(); - items.Add(itemId); - InventoryService.DeleteItems(senderId, items); - } - } - - return itemCopy; - } - else - { - m_log.WarnFormat("[AGENT INVENTORY]: Failed to find item {0} or item does not belong to giver ", itemId); + m_log.WarnFormat( + "[AGENT INVENTORY]: Failed to find item {0} sent by {1} to {2}", itemId, senderId, recipient); return null; } + if (item.Owner != senderId) + { + m_log.WarnFormat( + "[AGENT INVENTORY]: Attempt to send item {0} {1} to {2} failed because sender {3} did not match item owner {4}", + item.Name, item.ID, recipient, senderId, item.Owner); + return null; + } + + IUserManagement uman = RequestModuleInterface(); + if (uman != null) + uman.AddUser(item.CreatorIdAsUuid, item.CreatorData); + + if (!Permissions.BypassPermissions()) + { + if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) + return null; + } + + // Insert a copy of the item into the recipient + InventoryItemBase itemCopy = new InventoryItemBase(); + itemCopy.Owner = recipient; + itemCopy.CreatorId = item.CreatorId; + itemCopy.CreatorData = item.CreatorData; + itemCopy.ID = UUID.Random(); + itemCopy.AssetID = item.AssetID; + itemCopy.Description = item.Description; + itemCopy.Name = item.Name; + itemCopy.AssetType = item.AssetType; + itemCopy.InvType = item.InvType; + itemCopy.Folder = recipientFolderId; + + if (Permissions.PropagatePermissions() && recipient != senderId) + { + // Trying to do this right this time. This is evil. If + // you believe in Good, go elsewhere. Vampires and other + // evil creatores only beyond this point. You have been + // warned. + + // We're going to mask a lot of things by the next perms + // Tweak the next perms to be nicer to our data + // + // In this mask, all the bits we do NOT want to mess + // with are set. These are: + // + // Transfer + // Copy + // Modufy + uint permsMask = ~ ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify); + + // Now, reduce the next perms to the mask bits + // relevant to the operation + uint nextPerms = permsMask | (item.NextPermissions & + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify)); + + // nextPerms now has all bits set, except for the actual + // next permission bits. + + // This checks for no mod, no copy, no trans. + // This indicates an error or messed up item. Do it like + // SL and assume trans + if (nextPerms == permsMask) + nextPerms |= (uint)PermissionMask.Transfer; + + // Inventory owner perms are the logical AND of the + // folded perms and the root prim perms, however, if + // the root prim is mod, the inventory perms will be + // mod. This happens on "take" and is of little concern + // here, save for preventing escalation + + // This hack ensures that items previously permalocked + // get unlocked when they're passed or rezzed + uint basePerms = item.BasePermissions | + (uint)PermissionMask.Move; + uint ownerPerms = item.CurrentPermissions; + + // If this is an object, root prim perms may be more + // permissive than folded perms. Use folded perms as + // a mask + if (item.InvType == (int)InventoryType.Object) + { + // Create a safe mask for the current perms + uint foldedPerms = (item.CurrentPermissions & 7) << 13; + foldedPerms |= permsMask; + + bool isRootMod = (item.CurrentPermissions & + (uint)PermissionMask.Modify) != 0 ? + true : false; + + // Mask the owner perms to the folded perms + ownerPerms &= foldedPerms; + basePerms &= foldedPerms; + + // If the root was mod, let the mask reflect that + // We also need to adjust the base here, because + // we should be able to edit in-inventory perms + // for the root prim, if it's mod. + if (isRootMod) + { + ownerPerms |= (uint)PermissionMask.Modify; + basePerms |= (uint)PermissionMask.Modify; + } + } + + // These will be applied to the root prim at next rez. + // The slam bit (bit 3) and folded permission (bits 0-2) + // are preserved due to the above mangling + ownerPerms &= nextPerms; + + // Mask the base permissions. This is a conservative + // approach altering only the three main perms + basePerms &= nextPerms; + + // Assign to the actual item. Make sure the slam bit is + // set, if it wasn't set before. + itemCopy.BasePermissions = basePerms; + itemCopy.CurrentPermissions = ownerPerms; + itemCopy.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; + + itemCopy.NextPermissions = item.NextPermissions; + + // This preserves "everyone can move" + itemCopy.EveryOnePermissions = item.EveryOnePermissions & + nextPerms; + + // Intentionally killing "share with group" here, as + // the recipient will not have the group this is + // set to + itemCopy.GroupPermissions = 0; + } + else + { + itemCopy.CurrentPermissions = item.CurrentPermissions; + itemCopy.NextPermissions = item.NextPermissions; + itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions; + itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; + itemCopy.BasePermissions = item.BasePermissions; + } + + if (itemCopy.Folder == UUID.Zero) + { + InventoryFolderBase folder = InventoryService.GetFolderForType(recipient, (AssetType)itemCopy.AssetType); + + if (folder != null) + { + itemCopy.Folder = folder.ID; + } + else + { + InventoryFolderBase root = InventoryService.GetRootFolder(recipient); + + if (root != null) + itemCopy.Folder = root.ID; + else + return null; // No destination + } + } + + itemCopy.GroupID = UUID.Zero; + itemCopy.GroupOwned = false; + itemCopy.Flags = item.Flags; + itemCopy.SalePrice = item.SalePrice; + itemCopy.SaleType = item.SaleType; + + if (AddInventoryItem(itemCopy)) + { + IInventoryAccessModule invAccess = RequestModuleInterface(); + if (invAccess != null) + invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); + } + + if (!Permissions.BypassPermissions()) + { + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + { + List items = new List(); + items.Add(itemId); + InventoryService.DeleteItems(senderId, items); + } + } + + return itemCopy; } /// diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index 83f0686636..10c275e040 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -59,19 +59,24 @@ namespace OpenSim.Region.Framework.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); - UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, 1001); + UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, 1002); InventoryItemBase item1 = UserInventoryHelpers.CreateInventoryItem(scene, "item1", user1.PrincipalID); scene.GiveInventoryItem(user2.PrincipalID, user1.PrincipalID, item1.ID); InventoryItemBase retrievedItem1 - = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, user2.PrincipalID, "Objects/item1"); + = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, user2.PrincipalID, "Notecards/item1"); Assert.That(retrievedItem1, Is.Not.Null); // Try giving back the freshly received item - //scene.GiveInventoryItem(user1.PrincipalID, user2.PrincipalID, retrievedItem1.ID); + scene.GiveInventoryItem(user1.PrincipalID, user2.PrincipalID, retrievedItem1.ID); + + List reretrievedItems + = UserInventoryHelpers.GetInventoryItems(scene.InventoryService, user1.PrincipalID, "Notecards/item1"); + + Assert.That(reretrievedItems.Count, Is.EqualTo(2)); } [Test] @@ -81,8 +86,8 @@ namespace OpenSim.Region.Framework.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); - UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, 1001); + UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, 1002); InventoryFolderBase folder1 = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, "folder1"); diff --git a/OpenSim/Services/InventoryService/InventoryService.cs b/OpenSim/Services/InventoryService/InventoryService.cs index e543337c71..73dd06ac3a 100644 --- a/OpenSim/Services/InventoryService/InventoryService.cs +++ b/OpenSim/Services/InventoryService/InventoryService.cs @@ -340,6 +340,9 @@ namespace OpenSim.Services.InventoryService List itemsList = new List(); itemsList.AddRange(m_Database.getInventoryInFolder(folderID)); + +// m_log.DebugFormat( +// "[INVENTORY SERVICE]: Found {0} items in folder {1} for {2}", itemsList.Count, folderID, userID); return itemsList; } @@ -385,8 +388,9 @@ namespace OpenSim.Services.InventoryService // See IInventoryServices public virtual bool AddItem(InventoryItemBase item) { - m_log.DebugFormat( - "[INVENTORY SERVICE]: Adding item {0} {1} to folder {2}", item.Name, item.ID, item.Folder); +// m_log.DebugFormat( +// "[INVENTORY SERVICE]: Adding item {0} {1} to folder {2} for {3}", +// item.Name, item.ID, item.Folder, item.Owner); m_Database.addInventoryItem(item); diff --git a/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs b/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs index 8cfad79f28..d924ecd5c8 100644 --- a/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs @@ -117,17 +117,20 @@ namespace OpenSim.Tests.Common // } public static UserAccount CreateUserWithInventory(Scene scene) + { + return CreateUserWithInventory(scene, 99); + } + + public static UserAccount CreateUserWithInventory(Scene scene, int uuidTail) { return CreateUserWithInventory( - scene, "Bill", "Bailey", UUID.Parse("00000000-0000-0000-0000-000000000099"), "troll"); + scene, "Bill", "Bailey", new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", uuidTail)), "troll"); } public static UserAccount CreateUserWithInventory( Scene scene, string firstName, string lastName, UUID userId, string pw) { - UserAccount ua - = new UserAccount(userId) - { FirstName = firstName, LastName = lastName }; + UserAccount ua = new UserAccount(userId) { FirstName = firstName, LastName = lastName }; CreateUserWithInventory(scene, ua, pw); return ua; } diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs index 93b655a42b..875bf4ac2c 100644 --- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs @@ -65,15 +65,18 @@ namespace OpenSim.Tests.Common /// public static InventoryItemBase CreateInventoryItem(Scene scene, string itemName, UUID itemId, UUID userId) { + AssetBase asset = AssetHelpers.CreateAsset(scene, userId); InventoryItemBase item = new InventoryItemBase(); item.Name = itemName; - item.AssetID = AssetHelpers.CreateAsset(scene, userId).FullID; + item.AssetID = asset.FullID; item.ID = itemId; + item.Owner = userId; + item.AssetType = asset.Type; + item.InvType = (int)InventoryType.Notecard; + + InventoryFolderBase folder = scene.InventoryService.GetFolderForType(userId, AssetType.Notecard); - // Really quite bad since the objs folder could be moved in the future and confuse the tests - InventoryFolderBase objsFolder = scene.InventoryService.GetFolderForType(userId, AssetType.Object); - - item.Folder = objsFolder.ID; + item.Folder = folder.ID; scene.AddInventoryItem(item); return item; @@ -165,5 +168,17 @@ namespace OpenSim.Tests.Common { return InventoryArchiveUtils.FindItemByPath(inventoryService, userId, path); } + + /// + /// Get the inventory items that match the path name. + /// + /// + /// + /// + /// An empty list if no matching items were found. + public static List GetInventoryItems(IInventoryService inventoryService, UUID userId, string path) + { + return InventoryArchiveUtils.FindItemsByPath(inventoryService, userId, path); + } } } \ No newline at end of file From fe471b64245f99a895d661a8952fc3c226ba6bfe Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 4 Jun 2011 02:44:53 +0100 Subject: [PATCH 126/186] Extend TestGiveInventoryFolder() to test giving back the freshly received folder --- .../Framework/Scenes/Tests/UserInventoryTests.cs | 8 ++++++++ .../Tests/Common/Helpers/UserInventoryHelpers.cs | 15 +++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index 10c275e040..abca792b8d 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -97,6 +97,14 @@ namespace OpenSim.Region.Framework.Tests = UserInventoryHelpers.GetInventoryFolder(scene.InventoryService, user2.PrincipalID, "folder1"); Assert.That(retrievedFolder1, Is.Not.Null); + + // Try giving back the freshly received folder + scene.GiveInventoryFolder(user1.PrincipalID, user2.PrincipalID, retrievedFolder1.ID, UUID.Zero); + + List reretrievedFolders + = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, "folder1"); + + Assert.That(reretrievedFolders.Count, Is.EqualTo(2)); } } } \ No newline at end of file diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs index 875bf4ac2c..1703597549 100644 --- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs @@ -147,8 +147,7 @@ namespace OpenSim.Tests.Common /// null if no folder matching the path was found public static InventoryFolderBase GetInventoryFolder(IInventoryService inventoryService, UUID userId, string path) { - List folders - = InventoryArchiveUtils.FindFolderByPath(inventoryService, userId, path); + List folders = GetInventoryFolders(inventoryService, userId, path); if (folders.Count != 0) return folders[0]; @@ -156,6 +155,18 @@ namespace OpenSim.Tests.Common return null; } + /// + /// Get the inventory folders that match the path name. + /// + /// + /// + /// + /// An empty list if no matching folders were found + public static List GetInventoryFolders(IInventoryService inventoryService, UUID userId, string path) + { + return InventoryArchiveUtils.FindFolderByPath(inventoryService, userId, path); + } + /// /// Get the inventory item that matches the path name. If there are multiple items then only the first /// is returned. From 205b2f7ea4aacb66304d3e9a5c70c5001fdeda4d Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 4 Jun 2011 03:01:52 +0100 Subject: [PATCH 127/186] Remove the unmaintained 'CMS' framework, which was really a 'source-control' experiment from 2008. This hasn't been touched for about 2 years and I haven't being using it. If this is wrong then please let me know. --- .../ContentManagementSystem/AuraMetaEntity.cs | 161 ---- .../ContentManagementSystem/BeamMetaEntity.cs | 139 ---- .../ContentManagementSystem/CMController.cs | 756 ------------------ .../CMEntityCollection.cs | 193 ----- .../ContentManagementSystem/CMModel.cs | 365 --------- .../ContentManagementSystem/CMView.cs | 206 ----- .../ContentManagementEntity.cs | 375 --------- .../ContentManagementModule.cs | 163 ---- .../FileSystemDatabase.cs | 317 -------- .../ContentManagementSystem/GitDatabase.cs | 167 ---- .../IContentDatabase.cs | 94 --- .../ContentManagementSystem/MetaEntity.cs | 270 ------- .../PointMetaEntity.cs | 104 --- .../ContentManagementSystem/README | 52 -- .../SceneObjectGroupDiff.cs | 216 ----- 15 files changed, 3578 deletions(-) delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/README delete mode 100644 OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs deleted file mode 100644 index 4a402bf2bd..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs +++ /dev/null @@ -1,161 +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. - */ - -#region Header - -// AuraMetaEntity.cs created with MonoDevelop -// User: bongiojp at 3:03 PM 8/6/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class AuraMetaEntity : PointMetaEntity - { - #region Constructors - - //transparency of root part, NOT particle system. Should probably add support for changing particle system transparency. - public AuraMetaEntity(Scene scene, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) - : base(scene, groupPos, transparency) - { - SetAura(color, scale); - } - - public AuraMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) - : base(scene, uuid, groupPos, transparency) - { - SetAura(color, scale); - } - - #endregion Constructors - - #region Private Methods - - private float Average(Vector3 values) - { - return (values.X + values.Y + values.Z)/3f; - } - - #endregion Private Methods - - #region Public Methods - - public void SetAura(Vector3 color, Vector3 scale) - { - SetAura(color, Average(scale) * 2.0f); - } - - public void SetAura(Vector3 color, float radius) - { - SceneObjectPart From = m_Entity.RootPart; - - //m_log.Debug("[META ENTITY] BEFORE: radius = " + radius); - float burstRadius = 0.1f; - Primitive.ParticleSystem.SourcePattern patternFlags = Primitive.ParticleSystem.SourcePattern.None; - float age = 1.5f; - float burstRate = 0.4f; - if (radius >= 8.0f) - { - //float sizeOfObject = radius / 2.0f; - burstRadius = (radius - 8.0f)/3f; - burstRate = 1.5f; - radius = 7.99f; - patternFlags = Primitive.ParticleSystem.SourcePattern.Explode; - age = 4.0f; - } - SetAura(From, color, radius, burstRadius, age, burstRate, patternFlags); - } - - public void SetAura(SceneObjectPart From, Vector3 color, float radius, float burstRadius, float age, float burstRate, Primitive.ParticleSystem.SourcePattern patternFlags) - { - Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | - // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | - // Primitive.ParticleSystem.ParticleDataFlags.TargetPos; - prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR - prules.PartStartColor.G = color.Y; - prules.PartStartColor.B = color.Z; - prules.PartStartColor.A = 0.5f; //PSYS_PART_START_ALPHA, transparency - prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR - prules.PartEndColor.G = color.Y; - prules.PartEndColor.B = color.Z; - prules.PartEndColor.A = 0.5f; //PSYS_PART_END_ALPHA, transparency - /*prules.PartStartScaleX = 0.5f; //PSYS_PART_START_SCALE - prules.PartStartScaleY = 0.5f; - prules.PartEndScaleX = 0.5f; //PSYS_PART_END_SCALE - prules.PartEndScaleY = 0.5f; - */ - prules.PartStartScaleX = radius; //PSYS_PART_START_SCALE - prules.PartStartScaleY = radius; - prules.PartEndScaleX = radius; //PSYS_PART_END_SCALE - prules.PartEndScaleY = radius; - prules.PartMaxAge = age; //PSYS_PART_MAX_AGE - prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL - prules.PartAcceleration.Y = 0.0f; - prules.PartAcceleration.Z = 0.0f; - prules.Pattern = patternFlags; //PSYS_SRC_PATTERN - //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank - prules.BurstRate = burstRate; //PSYS_SRC_BURST_RATE - prules.BurstPartCount = 2; //PSYS_SRC_BURST_PART_COUNT - //prules.BurstRadius = radius; //PSYS_SRC_BURST_RADIUS - prules.BurstRadius = burstRadius; //PSYS_SRC_BURST_RADIUS - prules.BurstSpeedMin = 0.001f; //PSYS_SRC_BURST_SPEED_MIN - prules.BurstSpeedMax = 0.001f; //PSYS_SRC_BURST_SPEED_MAX - prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE - //prules.Target = To; //PSYS_SRC_TARGET_KEY - prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA - prules.AngularVelocity.Y = 0.0f; - prules.AngularVelocity.Z = 0.0f; - prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN - prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END - - prules.CRC = 1; //activates the particle system?? - From.AddNewParticleSystem(prules); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs deleted file mode 100644 index 6966de0cab..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.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. - */ - -#region Header - -// BeamMetaEntity.cs created with MonoDevelop -// User: bongiojp at 3:03 PM 8/6/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class BeamMetaEntity : PointMetaEntity - { - #region Constructors - - public BeamMetaEntity(Scene scene, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) - : base(scene, groupPos, transparency) - { - SetBeamToUUID(To, color); - } - - public BeamMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) - : base(scene, uuid, groupPos, transparency) - { - SetBeamToUUID(To, color); - } - - #endregion Constructors - - #region Public Methods - - public void SetBeamToUUID(SceneObjectPart To, Vector3 color) - { - SceneObjectPart From = m_Entity.RootPart; - //Scale size of particles to distance objects are apart (for better visibility) - Vector3 FromPos = From.GetWorldPosition(); - Vector3 ToPos = From.GetWorldPosition(); - // UUID toUUID = To.UUID; - float distance = (float) (Math.Sqrt(Math.Pow(FromPos.X-ToPos.X, 2) + - Math.Pow(FromPos.X-ToPos.Y, 2) + - Math.Pow(FromPos.X-ToPos.Z, 2) - ) - ); - //float rate = (float) (distance/4f); - float rate = 0.5f; - float scale = (float) (distance/128f); - float speed = (float) (2.0f - distance/128f); - - SetBeamToUUID(From, To, color, rate, scale, speed); - } - - public void SetBeamToUUID(SceneObjectPart From, SceneObjectPart To, Vector3 color, float rate, float scale, float speed) - { - Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | - // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS - prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | - Primitive.ParticleSystem.ParticleDataFlags.TargetPos; - prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR - prules.PartStartColor.G = color.Y; - prules.PartStartColor.B = color.Z; - prules.PartStartColor.A = 1.0f; //PSYS_PART_START_ALPHA, transparency - prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR - prules.PartEndColor.G = color.Y; - prules.PartEndColor.B = color.Z; - prules.PartEndColor.A = 1.0f; //PSYS_PART_END_ALPHA, transparency - prules.PartStartScaleX = scale; //PSYS_PART_START_SCALE - prules.PartStartScaleY = scale; - prules.PartEndScaleX = scale; //PSYS_PART_END_SCALE - prules.PartEndScaleY = scale; - prules.PartMaxAge = 1.0f; //PSYS_PART_MAX_AGE - prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL - prules.PartAcceleration.Y = 0.0f; - prules.PartAcceleration.Z = 0.0f; - //prules.Pattern = Primitive.ParticleSystem.SourcePattern.Explode; //PSYS_SRC_PATTERN - //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank - prules.BurstRate = rate; //PSYS_SRC_BURST_RATE - prules.BurstPartCount = 1; //PSYS_SRC_BURST_PART_COUNT - prules.BurstRadius = 0.5f; //PSYS_SRC_BURST_RADIUS - prules.BurstSpeedMin = speed; //PSYS_SRC_BURST_SPEED_MIN - prules.BurstSpeedMax = speed; //PSYS_SRC_BURST_SPEED_MAX - prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE - prules.Target = To.UUID; //PSYS_SRC_TARGET_KEY - prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA - prules.AngularVelocity.Y = 0.0f; - prules.AngularVelocity.Z = 0.0f; - prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN - prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END - - prules.CRC = 1; //activates the particle system?? - From.AddNewParticleSystem(prules); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs deleted file mode 100644 index 8d6c41df63..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs +++ /dev/null @@ -1,756 +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. - */ - -#region Header - -// CMController.cs -// User: bongiojp -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - /// - /// The controller in a Model-View-Controller framework. This controller catches actions by the avatars, creates work packets, loops through these work packets in a separate thread, - /// then dictates to the model how the data should change and dictates to the view which data should be displayed. The main mechanism for interaction is through the simchat system. - /// - public class CMController - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// The queue that keeps track of which actions have happened. The MainLoop thread eats through this queue. - /// - private static OpenSim.Framework.BlockingQueue m_WorkQueue = new OpenSim.Framework.BlockingQueue(); - - #endregion Static Fields - - #region Fields - - //bool init = false; - int m_channel = -1; - - /// - /// The estate module is used to identify which clients are estateManagers. Presently, the controller only pays attention to estate managers. - /// - IEstateModule m_estateModule = null; - - //These have to be global variables, threading doesn't allow for passing parameters. (Used in MainLoop) - CMModel m_model = null; - - /// - /// A list of all the scenes that should be revisioned. Controller is the only class that keeps track of all scenes in the region. - /// - Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable()); - State m_state = State.NONE; - CMView m_view = null; - - #endregion Fields - - #region Constructors - - /// - /// Initializes a work thread with an initial scene. Additional scenes should be added through the RegisterNewRegion method. - /// - /// - /// - /// - /// - /// - /// - /// - /// The first scene to keep track of. - /// - /// - /// The simchat channel number to listen to for instructions - /// - public CMController(CMModel model, CMView view, Scene scene, int channel) - { - m_model = model; m_view = view; m_channel = channel; - RegisterNewRegion(scene); - Initialize(model, view, scene, channel); - } - - #endregion Constructors - - #region Private Methods - - //------------------------------------------------ EVENTS ----------------------------------------------------// -// private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID) -// { -// } - - /// - /// Searches in all scenes for a SceneObjectGroup that contains a part with a specific localID. If found, the object is returned. Else null is returned. - /// - private SceneObjectGroup GetGroupByPrim(uint localID) - { - foreach (Object currScene in m_sceneList.Values) - { - foreach (EntityBase ent in ((Scene)currScene).GetEntities()) - { - if (ent is SceneObjectGroup) - { - if (((SceneObjectGroup)ent).HasChildPrim(localID)) - return (SceneObjectGroup)ent; - } - } - } - return null; - } - - private void Initialize(CMModel model, CMView view, Scene scene, int channel) - { - lock (this) - { - m_estateModule = scene.RequestModuleInterface(); - Watchdog.StartThread(MainLoop, "Content Management", ThreadPriority.Normal, true); - m_state = State.NONE; - } - } - - /// - /// Run in a thread of its own. A endless loop that consumes (or blocks on) and work queue. Thw work queue is filled through client actions. - /// - private void MainLoop() - { - try - { - CMModel model = m_model; CMView view = m_view; int channel = m_channel; - Work currentJob = new Work(); - while (true) - { - currentJob = m_WorkQueue.Dequeue(); - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- DeQueued a request"); - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Work type: " + currentJob.Type); - switch (currentJob.Type) - { - case WorkType.NONE: - break; - case WorkType.OBJECTATTRIBUTECHANGE: - ObjectAttributeChanged(model, view, currentJob.LocalId); - break; - case WorkType.PRIMITIVEADDED: - PrimitiveAdded(model, view, currentJob); - break; - case WorkType.OBJECTDUPLICATED: - ObjectDuplicated(model, view, currentJob.LocalId); - break; - case WorkType.OBJECTKILLED: - ObjectKilled(model, view, (SceneObjectGroup) currentJob.Data1); - break; - case WorkType.UNDODID: - UndoDid(model, view, currentJob.UUID); - break; - case WorkType.NEWCLIENT: - NewClient(view, (IClientAPI) currentJob.Data1); - break; - case WorkType.SIMCHAT: - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Message received: " + ((OSChatMessage) currentJob.Data1).Message); - SimChat(model, view, (OSChatMessage) currentJob.Data1, channel); - break; - default: - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?"); - break; - } - - Watchdog.UpdateThread(); - } - } - catch (Exception e) - { - // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened - m_log.ErrorFormat( - "[CONTENT MANAGEMENT]: Content management thread terminating with exception. PLEASE REBOOT YOUR SIM - CONTENT MANAGEMENT WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}", - e); - } - - Watchdog.RemoveThread(); - } - - /// - /// Only called by the MainLoop. Updates the view of a new client with metaentities if diff-mode is currently enabled. - /// - private void NewClient(CMView view, IClientAPI client) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - view.SendMetaEntitiesToNewClient(client); - } - - /// - /// Only called by the MainLoop. - /// - private void ObjectAttributeChanged(CMModel model, CMView view, uint LocalId) - { - SceneObjectGroup group = null; - if ((m_state & State.SHOWING_CHANGES) > 0) - { - group = GetGroupByPrim(LocalId); - if (group != null) - { - view.DisplayAuras(model.UpdateNormalEntityEffects(group)); //Might be a normal entity (green aura) - m_view.DisplayMetaEntity(group.UUID); //Might be a meta entity (blue aura) - } - } - } - - /// - /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied. - /// - private void ObjectDuplicated(CMModel model, CMView view, uint localId) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - view.DisplayAuras(model.CheckForNewEntitiesMissingAuras(GetGroupByPrim(localId).Scene)); - } - - /// - /// Only called by the MainLoop. - /// - private void ObjectKilled(CMModel model, CMView view, SceneObjectGroup group) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - view.RemoveOrUpdateDeletedEntity(group); - model.RemoveOrUpdateDeletedEntity(group); - } - } - - /// - /// Only called by the MainLoop. - /// - private void PrimitiveAdded(CMModel model, CMView view, Work currentJob) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - foreach (Object scene in m_sceneList.Values) - m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene) scene)); - } - } - - /// - /// Only called by the MainLoop. - /// - private void UndoDid(CMModel model, CMView view, UUID uuid) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid); - if (ent != null) - view.DisplayEntity(ent); - } - } - - #endregion Private Methods - - #region Protected Methods - - protected void GroupBeingDeleted(SceneObjectGroup group) - { - m_log.Debug("[CONTENT MANAGEMENT] Something was deleted!!!"); - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTKILLED; - moreWork.Data1 = group.Copy(); - m_WorkQueue.Enqueue(moreWork); - } - - protected void ObjectDuplicated(uint localID, Vector3 offset, uint dupeFlags, UUID AgentID, UUID GroupID) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTDUPLICATED; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] dup queue"); - } - - protected void ObjectDuplicatedOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, - UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart, - bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTDUPLICATED; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] dup queue"); - } - - protected void OnNewClient(IClientAPI client) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.NEWCLIENT; - moreWork.Data1 = client; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] new client"); - } - - protected void OnUnDid(IClientAPI remoteClient, UUID primId) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.UNDODID; - moreWork.UUID = primId; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] undid"); - } - - /// - /// Takes a list of scenes and forms a new orderd list according to the proximity of scenes to the second argument. - /// - protected static System.Collections.Generic.List ScenesInOrderOfProximity(Hashtable sceneList, Scene scene) - { - int somethingAddedToList = 1; - System.Collections.Generic.List newList = new List(); - newList.Add(scene); - - if (!sceneList.ContainsValue(scene)) - { - foreach (Object sceneObj in sceneList) - newList.Add((Scene) sceneObj); - return newList; - } - - while (somethingAddedToList > 0) - { - somethingAddedToList = 0; - for (int i = 0; i < newList.Count; i++) - { - foreach (Object sceneObj in sceneList.Values) - { - if (newList[i].CheckNeighborRegion(((Scene)sceneObj).RegionInfo) && (!newList.Contains((Scene)sceneObj))) - { - newList.Add((Scene)sceneObj); - somethingAddedToList++; - } - } - } - } - - foreach (Object sceneObj in sceneList.Values) - if (!newList.Contains((Scene)sceneObj)) - newList.Add((Scene)sceneObj); - - return newList; - } - - //This is stupid, the same information is contained in the first and second argument - protected void SimChatSent(Object x, OSChatMessage e) - { - m_log.Debug("[CONTENT MANAGEMENT] SIMCHAT SENT !!!!!!!"); - m_log.Debug("[CONTENT MANAGEMENT] message was: " + e.Message); - Work moreWork = new Work(); - moreWork.Type = WorkType.SIMCHAT; - moreWork.Data1 = e; - m_WorkQueue.Enqueue(moreWork); - } - - /// - /// Adds extra handlers to a number of events so that the controller can produce work based on the client's actions. - /// - protected void StartManaging(IClientAPI client) - { - m_log.Debug("[CONTENT MANAGEMENT] Registering channel with chat services."); - // client.OnChatFromClient += SimChatSent; - //init = true; - - OnNewClient(client); - - m_log.Debug("[CONTENT MANAGEMENT] Adding handlers to client."); - client.OnUpdatePrimScale += UpdateSingleScale; - client.OnUpdatePrimGroupScale += UpdateMultipleScale; - client.OnUpdatePrimGroupPosition += UpdateMultiplePosition; - client.OnUpdatePrimSinglePosition += UpdateSinglePosition; - client.OnUpdatePrimGroupRotation += UpdateMultipleRotation; - client.OnUpdatePrimSingleRotation += UpdateSingleRotation; - client.OnAddPrim += UpdateNewParts; - client.OnObjectDuplicate += ObjectDuplicated; - client.OnObjectDuplicateOnRay += ObjectDuplicatedOnRay; - client.OnUndo += OnUnDid; - //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; - } - - /// - /// - /// - protected void StopManaging(UUID clientUUID) - { - foreach (Object sceneobj in m_sceneList.Values) - { - ScenePresence presence = ((Scene)sceneobj).GetScenePresence(clientUUID); - if (presence != null) - { - IClientAPI client = presence.ControllingClient; - m_log.Debug("[CONTENT MANAGEMENT] Unregistering channel with chat services."); - // client.OnChatFromViewer -= SimChatSent; - - m_log.Debug("[CONTENT MANAGEMENT] Removing handlers to client"); - client.OnUpdatePrimScale -= UpdateSingleScale; - client.OnUpdatePrimGroupScale -= UpdateMultipleScale; - client.OnUpdatePrimGroupPosition -= UpdateMultiplePosition; - client.OnUpdatePrimSinglePosition -= UpdateSinglePosition; - client.OnUpdatePrimGroupRotation -= UpdateMultipleRotation; - client.OnUpdatePrimSingleRotation -= UpdateSingleRotation; - client.OnAddPrim -= UpdateNewParts; - client.OnObjectDuplicate -= ObjectDuplicated; - client.OnObjectDuplicateOnRay -= ObjectDuplicatedOnRay; - client.OnUndo -= OnUnDid; - //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; - return; - } - } - } - - protected void UpdateMultiplePosition(uint localID, Vector3 pos, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] pos"); - } - - protected void UpdateMultipleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] rot"); - } - - protected void UpdateMultipleScale(uint localID, Vector3 scale, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT]scale"); - } - - protected void UpdateNewParts(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape, - byte bypassRaycast, Vector3 RayStart, UUID RayTargetID, - byte RayEndIsIntersection) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.PRIMITIVEADDED; - moreWork.UUID = ownerID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] new parts"); - } - - protected void UpdateSinglePosition(uint localID, Vector3 pos, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] move"); - } - - /// - /// - /// - protected void UpdateSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] rot"); - } - - protected void UpdateSingleScale(uint localID, Vector3 scale, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] scale"); - } - - /// - /// Only called from within the SimChat method. - /// - protected void commit(string message, Scene scene, CMModel model, CMView view) - { - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - - string[] args = message.Split(new char[] {' '}); - - char[] logMessage = {' '}; - if (args.Length > 1) - { - logMessage = new char[message.Length - (args[0].Length)]; - message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length)); - } - - m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region."); - foreach (Scene currScene in proximitySceneList) - { - model.CommitRegion(currScene, new String(logMessage)); - view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName); - } - - view.SendSimChatMessage(scene, "Successfully saved all regions."); - m_state |= State.DIRTY; - - if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES - { - view.SendSimChatMessage(scene, "Updating differences between new revision and current environment."); - //Hide objects from users and Forget about them - view.HideAllMetaEntities(); - view.HideAllAuras(); - model.DeleteAllMetaObjects(); - - //Recreate them from backend files - foreach (Scene currScene in proximitySceneList) - { - model.UpdateCMEntities(currScene); - view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName); - } - - //Display new objects to users1 - view.DisplayRecentChanges(); - view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE."); - m_state &= ~(State.DIRTY); - m_state |= State.SHOWING_CHANGES; - } - } - - /// - /// Only called from within the SimChat method. - /// - protected void diffmode(Scene scene, CMModel model, CMView view) - { - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - - if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF - { - view.SendSimChatMessage(scene, "Hiding all meta objects."); - view.HideAllMetaEntities(); - view.HideAllAuras(); - view.SendSimChatMessage(scene, "Diff-mode = OFF"); - - m_state &= ~State.SHOWING_CHANGES; - return; - } - else // TURN ON - { - if ((m_state & State.DIRTY) != 0 || m_state == State.NONE) - { - view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision"); - //Hide objects from users and Forget about them - view.HideAllMetaEntities(); - view.HideAllAuras(); - model.DeleteAllMetaObjects(); - //Recreate them from backend files - foreach (Object currScene in m_sceneList.Values) - model.UpdateCMEntities((Scene) currScene); - } - else if ((m_state & State.DIRTY) != 0) { - view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision"); - foreach (Scene currScene in proximitySceneList) - model.UpdateCMEntities(currScene); - } - - view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment"); - foreach (Scene currScene in proximitySceneList) - model.CheckForNewEntitiesMissingAuras(currScene); - view.DisplayRecentChanges(); - - view.SendSimChatMessage(scene, "Diff-mode = ON"); - m_state |= State.SHOWING_CHANGES; - m_state &= ~State.DIRTY; - } - } - - /// - /// Only called from within the SimChat method. Hides all auras and meta entities, - /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene, - /// then lets the view update the clients of the new objects. - /// - protected void rollback(Scene scene, CMModel model, CMView view) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - view.HideAllAuras(); - view.HideAllMetaEntities(); - } - - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - foreach (Scene currScene in proximitySceneList) - model.RollbackRegion(currScene); - - if ((m_state & State.DIRTY) != 0) - { - model.DeleteAllMetaObjects(); - foreach (Scene currScene in proximitySceneList) - model.UpdateCMEntities(currScene); - } - - if ((m_state & State.SHOWING_CHANGES) > 0) - view.DisplayRecentChanges(); - } - - #endregion Protected Methods - - #region Public Methods - - /// - /// Register a new scene object to keep track of for revisioning. Starts the controller monitoring actions of clients within the given scene. - /// - /// - /// A - /// - public void RegisterNewRegion(Scene scene) - { - m_sceneList.Add(scene.RegionInfo.RegionID, scene); - - m_log.Debug("[CONTENT MANAGEMENT] Registering new region: " + scene.RegionInfo.RegionID); - m_log.Debug("[CONTENT MANAGEMENT] Initializing Content Management System."); - - scene.EventManager.OnNewClient += StartManaging; - scene.EventManager.OnChatFromClient += SimChatSent; - scene.EventManager.OnRemovePresence += StopManaging; - // scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; - scene.EventManager.OnObjectBeingRemovedFromScene += GroupBeingDeleted; - } - - /// - /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command. - /// - public void SimChat(CMModel model, CMView view, OSChatMessage e, int channel) - { - if (e.Channel != channel) - return; - if (e.Sender == null) - return; - - m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message); - - IClientAPI client = e.Sender; - Scene scene = (Scene) e.Scene; - string message = e.Message; - string[] args = e.Message.Split(new char[] {' '}); - - ScenePresence avatar = scene.GetScenePresence(client.AgentId); - - if (!(m_estateModule.IsManager(avatar.UUID))) - { - m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring."); - view.SendSimChatMessage(scene, "You must be an estate manager to perform that action."); - return; - } - - switch (args[0]) - { - case "ci": - case "commit": - commit(message, scene, model, view); - break; - case "dm": - case "diff-mode": - diffmode(scene, model, view); - break; - case "rb": - case "rollback": - rollback(scene, model, view); - break; - case "help": - m_view.DisplayHelpMenu(scene); - break; - default: - view.SendSimChatMessage(scene, "Command not found: " + args[0]); - break; - } - } - - #endregion Public Methods - - #region Other - - /// - /// Used to keep track of whether a list has been produced yet and whether that list is up-to-date compard to latest revision on disk. - /// - [Flags] - private enum State - { - NONE = 0, - DIRTY = 1, // The meta entities may not correctly represent the last revision. - SHOWING_CHANGES = 1<<1 // The meta entities are being shown to user. - } - - /// - /// The structure that defines the basic unit of work which is produced when a user sends commands to the ContentMangaementSystem. - /// - private struct Work - { - #region Fields - - public Object Data1; //Just space for holding data. - public Object Data2; //Just more space for holding data. - public uint LocalId; //Convenient - public WorkType Type; - public UUID UUID; //Convenient - - #endregion Fields - } - - /// - /// Identifies what the data in struct Work should be used for. - /// - private enum WorkType - { - NONE, - OBJECTATTRIBUTECHANGE, - PRIMITIVEADDED, - OBJECTDUPLICATED, - OBJECTKILLED, - UNDODID, - NEWCLIENT, - SIMCHAT - } - - #endregion Other - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs deleted file mode 100644 index 7f64ebdbf7..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs +++ /dev/null @@ -1,193 +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. - */ - -#region Header - -// CMEntityCollection.cs created with MonoDevelop -// User: bongiojp at 10:09 AM 7/7/2008 -// -// Creates, Deletes, Stores ContentManagementEntities -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class CMEntityCollection - { - #region Fields - - // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - // Any ContentManagementEntities that represent old versions of current SceneObjectGroups or - // old versions of deleted SceneObjectGroups will be stored in this hash table. - // The UUID keys are from the SceneObjectGroup RootPart UUIDs - protected Hashtable m_CMEntityHash = Hashtable.Synchronized(new Hashtable()); //UUID to ContentManagementEntity - - // SceneObjectParts that have not been revisioned will be given green auras stored in this hashtable - // The UUID keys are from the SceneObjectPart that they are supposed to be on. - protected Hashtable m_NewlyCreatedEntityAura = Hashtable.Synchronized(new Hashtable()); //UUID to AuraMetaEntity - - #endregion Fields - - #region Constructors - - public CMEntityCollection() - { - } - - #endregion Constructors - - #region Public Properties - - public Hashtable Auras - { - get {return m_NewlyCreatedEntityAura; } - } - - public Hashtable Entities - { - get { return m_CMEntityHash; } - } - - #endregion Public Properties - - #region Public Methods - - public bool AddAura(ContentManagementEntity aura) - { - if (m_NewlyCreatedEntityAura.ContainsKey(aura.UUID)) - return false; - m_NewlyCreatedEntityAura.Add(aura.UUID, aura); - return true; - } - - public bool AddEntity(ContentManagementEntity ent) - { - if (m_CMEntityHash.ContainsKey(ent.UUID)) - return false; - m_CMEntityHash.Add(ent.UUID, ent); - return true; - } - - // Check if there are SceneObjectGroups in the list that do not have corresponding ContentManagementGroups in the CMEntityHash - public System.Collections.ArrayList CheckForMissingEntities(EntityBase[] currList) - { - System.Collections.ArrayList missingList = new System.Collections.ArrayList(); - SceneObjectGroup temp = null; - foreach (EntityBase currObj in currList) - { - if (!(currObj is SceneObjectGroup)) - continue; - temp = (SceneObjectGroup) currObj; - - if (m_CMEntityHash.ContainsKey(temp.UUID)) - { - foreach (SceneObjectPart part in temp.Parts) - if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID)) - missingList.Add(part); - } - else //Entire group is missing from revision. (and is a new part in region) - { - foreach (SceneObjectPart part in temp.Parts) - missingList.Add(part); - } - } - return missingList; - } - - public void ClearAll() - { - m_CMEntityHash.Clear(); - m_NewlyCreatedEntityAura.Clear(); - } - - // Old uuid and new sceneobjectgroup - public AuraMetaEntity CreateAuraForNewlyCreatedEntity(SceneObjectPart part) - { - AuraMetaEntity ent = new AuraMetaEntity(part.ParentGroup.Scene, - part.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(0,254,0), - part.Scale - ); - m_NewlyCreatedEntityAura.Add(part.UUID, ent); - return ent; - } - - // Old uuid and new sceneobjectgroup - public ContentManagementEntity CreateNewEntity(SceneObjectGroup group) - { - ContentManagementEntity ent = new ContentManagementEntity(group, false); - m_CMEntityHash.Add(group.UUID, ent); - return ent; - } - - public ContentManagementEntity CreateNewEntity(String xml, Scene scene) - { - ContentManagementEntity ent = new ContentManagementEntity(xml, scene, false); - if (ent == null) - return null; - m_CMEntityHash.Add(ent.UnchangedEntity.UUID, ent); - return ent; - } - - public bool RemoveEntity(UUID uuid) - { - if (!m_CMEntityHash.ContainsKey(uuid)) - return false; - m_CMEntityHash.Remove(uuid); - return true; - } - - public bool RemoveNewlyCreatedEntityAura(UUID uuid) - { - if (!m_NewlyCreatedEntityAura.ContainsKey(uuid)) - return false; - m_NewlyCreatedEntityAura.Remove(uuid); - return true; - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs deleted file mode 100644 index 3a6996ef9b..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs +++ /dev/null @@ -1,365 +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; -using System.Collections.Generic; -using System.Diagnostics; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class CMModel - { - #region Static Fields - - static float TimeToUpdate = 0; - static float TimeToConvertXml = 0; - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - /// - /// The class that contains all auras and metaentities used in the CMS. - /// - CMEntityCollection m_MetaEntityCollection = new CMEntityCollection(); - IContentDatabase m_database = null; - - #endregion Fields - - #region Constructors - - public CMModel() - { - } - - #endregion Constructors - - #region Public Properties - - public CMEntityCollection MetaEntityCollection - { - get { return m_MetaEntityCollection; } - } - - #endregion Public Properties - - #region Public Methods - - /// - /// Compares the scene's object group list to the list of meta entities. If there is an object group that does not have a corresponding meta entity - /// it is a new part that must have a green aura (for diff mode). - /// Returns list of ContentManagementEntities - /// - public ArrayList CheckForNewEntitiesMissingAuras(Scene scene) - { - ArrayList missingList = null; - ArrayList newList = new ArrayList(); - - m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName); - - //Check if the current scene has groups not included in the current list of MetaEntities - //If so, then the current scene's parts that are new should be marked green. - missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities()); - - foreach (Object missingPart in missingList) - { - if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID)) - continue; - newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart)); - } - m_log.Info("Number of missing objects found: " + newList.Count); - return newList; - } - - /// - /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message. - /// - public void CommitRegion(Scene scene, String logMessage) - { - m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length); - m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage); - m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName); - } - - public void DeleteAllMetaObjects() - { - m_MetaEntityCollection.ClearAll(); - } - - public ContentManagementEntity FindMetaEntityAffectedByUndo(UUID uuid) - { - ContentManagementEntity ent = GetMetaGroupByPrim(uuid); - return ent; - } - - //-------------------------------- HELPERS --------------------------------------------------------------------// - public ContentManagementEntity GetMetaGroupByPrim(UUID uuid) - { - foreach (Object ent in m_MetaEntityCollection.Entities.Values) - { - if (((ContentManagementEntity)ent).HasChildPrim(uuid)) - return (ContentManagementEntity)ent; - } - return null; - } - - public void Initialise(string database) - { - if (database == "FileSystemDatabase") - m_database = new FileSystemDatabase(); - else if (database == "GitDatabase") - m_database = new GitDatabase(); - } - - public void InitialiseDatabase(Scene scene, string dir) - { - m_database.Initialise(scene, dir); - } - - /// - /// Should be called just once to finish initializing the database. - /// - public void PostInitialise() - { - m_database.PostInitialise(); - } - - /// - /// Removes the green aura when an a new scene object group is deleted. - /// - public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) - { - // Deal with new parts not revisioned that have been deleted. - SceneObjectPart[] parts = group.Parts; - for (int i = 0; i < parts.Length; i++) - { - if (m_MetaEntityCollection.Auras.ContainsKey(parts[i].UUID)) - m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(parts[i].UUID); - } - } - - /// - /// Retrieves the latest revision of a region in xml form, - /// converts it to scene object groups and scene presences, - /// swaps the current scene's entity list with the revision's list. - /// Note: Since deleted objects while - /// - public void RollbackRegion(Scene scene) - { - System.Collections.ArrayList xmllist = null; - SceneObjectGroup temp = null; - System.Collections.Hashtable deleteListUUIDs = new Hashtable(); -// Dictionary SearchList = new Dictionary(); - Dictionary ReplacementList = new Dictionary(); - int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID); -// EntityBase[] searchArray; - - xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision); - if (xmllist == null) - { - m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ")."); - return; - } - - m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ")."); - m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count); - m_log.Info("[CMMODEL]: Converting scene entities list to specified revision."); - - m_log.ErrorFormat("[CMMODEL]: 1"); - - foreach (string xml in xmllist) - { - try - { - temp = SceneObjectSerializer.FromXml2Format(xml); - temp.SetScene(scene); - - SceneObjectPart[] parts = temp.Parts; - for (int i = 0; i < parts.Length; i++) - parts[i].RegionHandle = scene.RegionInfo.RegionHandle; - - ReplacementList.Add(temp.UUID, (EntityBase)temp); - } - catch (Exception e) - { - m_log.Info("[CMMODEL]: Error while creating replacement list for rollback: " + e); - } - } - - //If in scene but not in revision and not a client, remove them - while (true) - { - try - { - foreach (EntityBase entity in scene.GetEntities()) - { - if (entity == null) - continue; - - if (entity is ScenePresence) - { - ReplacementList.Add(entity.UUID, entity); - continue; - } - else //if (!ReplacementList.ContainsKey(entity.UUID)) - deleteListUUIDs.Add(entity.UUID, 0); - } - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: " + e); - deleteListUUIDs.Clear(); - ReplacementList.Clear(); - continue; - } - break; - } - - foreach (UUID uuid in deleteListUUIDs.Keys) - { - try - { - // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles. - ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup(); - scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor); - scene.SendKillObject(scene.Entities[uuid].LocalId); - scene.SceneGraph.DeleteSceneObject(uuid, false); - ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroupFromScene(false); - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e); - } - } - - lock (scene) - { - scene.Entities.Clear(); - - foreach (KeyValuePair kvp in ReplacementList) - { - scene.Entities.Add(kvp.Value); - } - } - - foreach (EntityBase ent in ReplacementList.Values) - { - try - { - if (!(ent is SceneObjectGroup)) - continue; - - if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) PrimFlags.Phantom) == 0) - ((SceneObjectGroup)ent).ApplyPhysics(true); - ((SceneObjectGroup)ent).AttachToBackup(); - ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected. - ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: Error while attaching new scene entities to backup and scheduling for a full update: " + e); - } - } - m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup."); - scene.Backup(true); - } - - /// - /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences - /// and display the differences to clients. - /// - public void UpdateCMEntities(Scene scene) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - System.Collections.ArrayList xmllist = null; - m_log.Debug("[CONTENT MANAGEMENT] Retrieving object xml files for region: " + scene.RegionInfo.RegionID); - xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID); - m_log.Info("[FSDB]: got list"); - if (xmllist == null) - return; - - Stopwatch y = new Stopwatch(); - y.Start(); - foreach (string xml in xmllist) - m_MetaEntityCollection.CreateNewEntity(xml, scene); - y.Stop(); - TimeToConvertXml += y.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml); - - m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras"); - CheckForNewEntitiesMissingAuras(scene); - - x.Stop(); - TimeToUpdate += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate); - } - - /// - /// Detects if a scene object group from the scene list has moved or changed scale. The green aura - /// that surrounds the object is then moved or scaled with the group. - /// - public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group) - { - System.Collections.ArrayList auraList = new System.Collections.ArrayList(); - if (group == null) - return null; - - SceneObjectPart[] parts = group.Parts; - for (int i = 0; i < parts.Length; i++) - { - SceneObjectPart part = parts[i]; - if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) - { - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0, 254, 0), part.Scale); - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); - auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); - } - } - - return auraList; - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs deleted file mode 100644 index 3807ccda47..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs +++ /dev/null @@ -1,206 +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. - */ - -#region Header - -// CMView.cs created with MonoDevelop -// User: bongiojp at 11:57 AM 7/3/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class CMView - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - CMModel m_model = null; - - #endregion Fields - - #region Constructors - - public CMView() - { - } - - #endregion Constructors - - #region Public Methods - - // Auras To - public void DisplayAuras(CMEntityCollection auraCollection) - { - foreach (Object ent in auraCollection.Auras.Values) - ((AuraMetaEntity)ent).SendFullUpdateToAll(); - } - - // Auras To Client - public void DisplayAuras(CMEntityCollection auraCollection, IClientAPI client) - { - foreach (Object ent in auraCollection.Auras.Values) - ((AuraMetaEntity)ent).SendFullUpdate(client); - } - - // Auras from List To ALL - public void DisplayAuras(ArrayList list) - { - foreach (Object ent in list) - { - m_log.Debug("[CONTENT MANAGEMENT] displaying new aura riiiiiiiiiiiight NOW"); - ((AuraMetaEntity)ent).SendFullUpdateToAll(); - } - } - - // Entities to ALL - public void DisplayEntities(CMEntityCollection entityCollection) - { - foreach (Object ent in entityCollection.Entities.Values) - ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); - } - - // Entities to Client - public void DisplayEntities(CMEntityCollection entityCollection, IClientAPI client) - { - foreach (Object ent in entityCollection.Entities.Values) - ((ContentManagementEntity)ent).SendFullDiffUpdate(client); - } - - // Entities from List to ALL - public void DisplayEntities(ArrayList list) - { - foreach (Object ent in list) - ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); - } - - // Entity to ALL - public void DisplayEntity(ContentManagementEntity ent) - { - ent.SendFullDiffUpdateToAll(); - } - - public void DisplayHelpMenu(Scene scene) - { - string menu = "Menu:\n"; - menu += "commit (ci) - saves current state of the region to a database on the server\n"; - menu += "diff-mode (dm) - displays those aspects of region that have not been saved but changed since the very last revision. Will dynamically update as you change environment.\n"; - SendSimChatMessage(scene, menu); - } - - public void DisplayMetaEntity(UUID uuid) - { - ContentManagementEntity group = m_model.GetMetaGroupByPrim(uuid); - if (group != null) - group.SendFullDiffUpdateToAll(); - } - - /// - /// update all clients of red/green/blue auras and meta entities that the model knows about. - /// - public void DisplayRecentChanges() - { - m_log.Debug("[CONTENT MANAGEMENT] Sending update to clients for " + m_model.MetaEntityCollection.Entities.Count + " objects."); - DisplayEntities(m_model.MetaEntityCollection); - DisplayAuras(m_model.MetaEntityCollection); - } - - public void Hide(ContentManagementEntity ent) - { - ent.HideFromAll(); - } - - public void HideAllAuras() - { - foreach (Object obj in m_model.MetaEntityCollection.Auras.Values) - ((MetaEntity)obj).HideFromAll(); - } - - public void HideAllMetaEntities() - { - foreach (Object obj in m_model.MetaEntityCollection.Entities.Values) - ((ContentManagementEntity)obj).HideFromAll(); - } - - public void Initialise(CMModel model) - { - m_model = model; - } - - /// - /// Figures out if the part deleted was a new scene object part or a revisioned part that's been deleted. - /// If it's a new scene object, any green aura attached to it is deleted. - /// If a revisioned part is deleted, a new full update is sent to the environment of the meta entity, which will - /// figure out that there should be a red aura and not a blue aura/beam. - /// - public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) - { - // Deal with revisioned parts that have been deleted. - if (m_model.MetaEntityCollection.Entities.ContainsKey(group.UUID)) - ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); - - // Deal with new parts not revisioned that have been deleted. - foreach (SceneObjectPart part in group.Parts) - if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) - ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); - } - - public void SendMetaEntitiesToNewClient(IClientAPI client) - { - } - - public void SendSimChatMessage(Scene scene, string message) - { - scene.SimChat(Utils.StringToBytes(message), - ChatTypeEnum.Broadcast, 0, new Vector3(0,0,0), "Content Manager", UUID.Zero, false); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs deleted file mode 100644 index 0248f368f2..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs +++ /dev/null @@ -1,375 +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 System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class ContentManagementEntity : MetaEntity - { - #region Static Fields - -// static float TimeToDiff = 0; -// static float TimeToCreateEntities = 0; - - #endregion Static Fields - - #region Fields - - protected Dictionary m_AuraEntities = new Dictionary(); - protected Dictionary m_BeamEntities = new Dictionary(); - - // The LinkNum of parts in m_Entity and m_UnchangedEntity are the same though UUID and LocalId are different. - // This can come in handy. - protected SceneObjectGroup m_UnchangedEntity = null; - - /// - /// Should be set to true when there is a difference between m_UnchangedEntity and the corresponding scene object group in the scene entity list. - /// - bool DiffersFromSceneGroup = false; - - #endregion Fields - - #region Constructors - - public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics) - : base(Unchanged, false) - { - m_UnchangedEntity = Unchanged.Copy(false); - } - - public ContentManagementEntity(string objectXML, Scene scene, bool physics) - : base(objectXML, scene, false) - { - m_UnchangedEntity = SceneObjectSerializer.FromXml2Format(objectXML); - } - - #endregion Constructors - - #region Public Properties - - public SceneObjectGroup UnchangedEntity - { - get { return m_UnchangedEntity; } - } - - #endregion Public Properties - - #region Private Methods - - /// - /// Check if an entitybase list (like that returned by scene.GetEntities()) contains a group with the rootpart uuid that matches the current uuid. - /// - private bool ContainsKey(List list, UUID uuid) - { - foreach (EntityBase part in list) - if (part.UUID == uuid) - return true; - return false; - } - - private SceneObjectGroup GetGroupByUUID(System.Collections.Generic.List list, UUID uuid) - { - foreach (EntityBase ent in list) - { - if (ent is SceneObjectGroup) - if (ent.UUID == uuid) - return (SceneObjectGroup)ent; - } - return null; - } - - #endregion Private Methods - - #region Public Methods - - /// - /// Search for a corresponding group UUID in the scene. If not found, then the revisioned group this CMEntity represents has been deleted. Mark the metaentity appropriately. - /// If a matching UUID is found in a scene object group, compare the two for differences. If differences exist, Mark the metaentity appropriately. - /// - public void FindDifferences() - { - List sceneEntityList = new List(m_Entity.Scene.GetEntities()); - DiffersFromSceneGroup = false; - // if group is not contained in scene's list - if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) - { - foreach (SceneObjectPart part in m_UnchangedEntity.Parts) - { - // if scene list no longer contains this part, display translucent part and mark with red aura - if (!ContainsKey(sceneEntityList, part.UUID)) - { - // if already displaying a red aura over part, make sure its red - if (m_AuraEntities.ContainsKey(part.UUID)) - { - m_AuraEntities[part.UUID].SetAura(new Vector3(254, 0, 0), part.Scale); - } - else - { - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - part.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(254, 0, 0), - part.Scale - ); - m_AuraEntities.Add(part.UUID, auraGroup); - } - SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum); - SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT); - } - // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id - } - - // a deleted part has no where to point a beam particle system, - // if a metapart had a particle system (maybe it represented a moved part) remove it - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - - DiffersFromSceneGroup = true; - } - // if scene list does contain group, compare each part in group for differences and display beams and auras appropriately - else - { - MarkWithDifferences((SceneObjectGroup)GetGroupByUUID(sceneEntityList, m_UnchangedEntity.UUID)); - } - } - - /// - /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given UUID. - /// - public bool HasChildPrim(UUID uuid) - { - return m_UnchangedEntity.ContainsPart(uuid); - } - - /// - /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId. - /// - public bool HasChildPrim(uint localID) - { - foreach (SceneObjectPart part in m_UnchangedEntity.Parts) - if (part.LocalId == localID) - return true; - - return false; - } - - public override void Hide(IClientAPI client) - { - base.Hide(client); - foreach (MetaEntity group in m_AuraEntities.Values) - group.Hide(client); - foreach (MetaEntity group in m_BeamEntities.Values) - group.Hide(client); - } - - public override void HideFromAll() - { - base.HideFromAll(); - foreach (MetaEntity group in m_AuraEntities.Values) - group.HideFromAll(); - foreach (MetaEntity group in m_BeamEntities.Values) - group.HideFromAll(); - } - - /// - /// Returns true if there was a change between meta entity and the entity group, false otherwise. - /// If true is returned, it is assumed the metaentity's appearance has changed to reflect the difference (though clients haven't been updated). - /// - public bool MarkWithDifferences(SceneObjectGroup sceneEntityGroup) - { - SceneObjectPart sceneEntityPart; - SceneObjectPart metaEntityPart; - Diff differences; - bool changed = false; - - // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user - // had originally saved. - // m_Entity will NOT necessarily be the same entity as the user had saved. - foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Parts) - { - //This is the part that we use to show changes. - metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); - if (sceneEntityGroup.ContainsPart(UnchangedPart.UUID)) - { - sceneEntityPart = sceneEntityGroup.GetChildPart(UnchangedPart.UUID); - differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); - if (differences != Diff.NONE) - metaEntityPart.Text = "CHANGE: " + differences.ToString(); - if (differences != 0) - { - // Root Part that has been modified - if ((differences & Diff.POSITION) > 0) - { - // If the position of any part has changed, make sure the RootPart of the - // meta entity is pointing with a beam particle system - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene, - m_UnchangedEntity.RootPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - sceneEntityPart, - new Vector3(0, 0, 254) - ); - m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup); - } - - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - UnchangedPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(0, 0, 254), - UnchangedPart.Scale - ); - m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); - SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - - DiffersFromSceneGroup = true; - } - else // no differences between scene part and meta part - { - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - SetPartTransparency(metaEntityPart, MetaEntity.NONE); - } - } - else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted. - { - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - UnchangedPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(254, 0, 0), - UnchangedPart.Scale - ); - m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); - SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - - DiffersFromSceneGroup = true; - } - } - - return changed; - } - - public void SendFullAuraUpdate(IClientAPI client) - { - if (DiffersFromSceneGroup) - { - foreach (AuraMetaEntity group in m_AuraEntities.Values) - group.SendFullUpdate(client); - } - } - - public void SendFullAuraUpdateToAll() - { - if (DiffersFromSceneGroup) - { - foreach (AuraMetaEntity group in m_AuraEntities.Values) - group.SendFullUpdateToAll(); - } - } - - public void SendFullBeamUpdate(IClientAPI client) - { - if (DiffersFromSceneGroup) - { - foreach (BeamMetaEntity group in m_BeamEntities.Values) - group.SendFullUpdate(client); - } - } - - public void SendFullBeamUpdateToAll() - { - if (DiffersFromSceneGroup) - { - foreach (BeamMetaEntity group in m_BeamEntities.Values) - group.SendFullUpdateToAll(); - } - } - - public void SendFullDiffUpdate(IClientAPI client) - { - FindDifferences(); - if (DiffersFromSceneGroup) - { - SendFullUpdate(client); - SendFullAuraUpdate(client); - SendFullBeamUpdate(client); - } - } - - public void SendFullDiffUpdateToAll() - { - FindDifferences(); - if (DiffersFromSceneGroup) - { - SendFullUpdateToAll(); - SendFullAuraUpdateToAll(); - SendFullBeamUpdateToAll(); - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs deleted file mode 100644 index 3d1c346dc8..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs +++ /dev/null @@ -1,163 +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. - */ - -#region Header - -// ContentManagementModule.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Threading; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class ContentManagementModule : IRegionModule - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - bool initialised = false; - CMController m_control = null; - bool m_enabled = false; - CMModel m_model = null; - bool m_posted = false; - CMView m_view = null; - - #endregion Fields - - #region Public Properties - - public bool IsSharedModule - { - get { return true; } - } - - public string Name - { - get { return "ContentManagementModule"; } - } - - #endregion Public Properties - - #region Public Methods - - public void Close() - { - } - - public void Initialise(Scene scene, IConfigSource source) - { - string databaseDir = "./"; - string database = "FileSystemDatabase"; - int channel = 345; - try - { - if (source.Configs["CMS"] == null) - return; - - m_enabled = source.Configs["CMS"].GetBoolean("enabled", false); - databaseDir = source.Configs["CMS"].GetString("directory", databaseDir); - database = source.Configs["CMS"].GetString("database", database); - channel = source.Configs["CMS"].GetInt("channel", channel); - - if (database != "FileSystemDatabase" && database != "GitDatabase") - { - m_log.ErrorFormat("[Content Management]: The Database attribute must be defined as either FileSystemDatabase or GitDatabase"); - m_enabled = false; - } - } - catch (Exception e) - { - m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e); - m_enabled = false; - } - - if (!m_enabled) - { - m_log.Info("[Content Management]: Content Management System is not Enabled."); - return; - } - - lock (this) - { - if (!initialised) //only init once - { - m_view = new CMView(); - m_model = new CMModel(); - m_control = new CMController(m_model, m_view, scene, channel); - m_model.Initialise(database); - m_view.Initialise(m_model); - - initialised = true; - m_model.InitialiseDatabase(scene, databaseDir); - } - else - { - m_model.InitialiseDatabase(scene, databaseDir); - m_control.RegisterNewRegion(scene); - } - } - } - - public void PostInitialise() - { - if (! m_enabled) - return; - - lock (this) - { - if (!m_posted) //only post once - { - m_model.PostInitialise(); - m_posted = true; - } - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs deleted file mode 100644 index a3d7977006..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs +++ /dev/null @@ -1,317 +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. - */ - -#region Header - -// FileSystemDatabase.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using Slash = System.IO.Path; -using System.Reflection; -using System.Xml; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class FileSystemDatabase : IContentDatabase - { - #region Static Fields - - public static float TimeToDownload = 0; - public static float TimeToSave = 0; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - private string m_repodir = null; - private Dictionary m_scenes = new Dictionary(); - private Dictionary m_serialiser = new Dictionary(); - - #endregion Fields - - #region Constructors - - public FileSystemDatabase() - { - } - - #endregion Constructors - - #region Private Methods - - // called by postinitialise - private void CreateDirectory() - { - string scenedir; - if (!Directory.Exists(m_repodir)) - Directory.CreateDirectory(m_repodir); - - foreach (UUID region in m_scenes.Keys) - { - scenedir = m_repodir + Slash.DirectorySeparatorChar + region + Slash.DirectorySeparatorChar; - if (!Directory.Exists(scenedir)) - Directory.CreateDirectory(scenedir); - } - } - - // called by postinitialise - private void SetupSerialiser() - { - if (m_serialiser.Count == 0) - { - foreach (UUID region in m_scenes.Keys) - { - m_serialiser.Add(region, m_scenes[region].RequestModuleInterface()); - } - } - } - - #endregion Private Methods - - #region Public Methods - - public int GetMostRecentRevision(UUID regionid) - { - return NumOfRegionRev(regionid); - } - - public string GetRegionObjectHeightMap(UUID regionid) - { - String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + - Slash.DirectorySeparatorChar + "heightmap.r32"; - FileStream fs = new FileStream(filename, FileMode.Open); - StreamReader sr = new StreamReader(fs); - String result = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - return result; - } - - public string GetRegionObjectHeightMap(UUID regionid, int revision) - { - String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + - Slash.DirectorySeparatorChar + "heightmap.r32"; - FileStream fs = new FileStream(filename, FileMode.Open); - StreamReader sr = new StreamReader(fs); - String result = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - return result; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) - { - System.Collections.ArrayList objectList = new System.Collections.ArrayList(); - string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + - + revision + Slash.DirectorySeparatorChar + "objects.xml"; - XmlDocument doc = new XmlDocument(); - XmlNode rootNode; - //int primCount = 0; - //SceneObjectGroup obj = null; - - if (File.Exists(filename)) - { - XmlTextReader reader = new XmlTextReader(filename); - reader.WhitespaceHandling = WhitespaceHandling.None; - doc.Load(reader); - reader.Close(); - rootNode = doc.FirstChild; - foreach (XmlNode aPrimNode in rootNode.ChildNodes) - { - objectList.Add(aPrimNode.OuterXml); - } - return objectList; - } - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) - { - int revision = NumOfRegionRev(regionid); - m_log.Info("[FSDB]: found revisions:" + revision); - System.Collections.ArrayList xmlList = new System.Collections.ArrayList(); - string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + - + revision + Slash.DirectorySeparatorChar + "objects.xml"; - XmlDocument doc = new XmlDocument(); - XmlNode rootNode; - - m_log.Info("[FSDB]: Checking if " + filename + " exists."); - if (File.Exists(filename)) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - XmlTextReader reader = new XmlTextReader(filename); - reader.WhitespaceHandling = WhitespaceHandling.None; - doc.Load(reader); - reader.Close(); - rootNode = doc.FirstChild; - - foreach (XmlNode aPrimNode in rootNode.ChildNodes) - { - xmlList.Add(aPrimNode.OuterXml); - } - - x.Stop(); - TimeToDownload += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent retrieving xml files so far: " + TimeToDownload); - - return xmlList; - } - return null; - } - - public void Initialise(Scene scene, string dir) - { - lock (this) - { - if (m_repodir == null) - m_repodir = dir; - } - lock (m_scenes) - m_scenes.Add(scene.RegionInfo.RegionID, scene); - } - - public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID regionid) - { - SortedDictionary revisionDict = new SortedDictionary(); - - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - string[] directories = Directory.GetDirectories(scenedir); - - FileStream fs = null; - StreamReader sr = null; - String logMessage = ""; - String logLocation = ""; - foreach (string revisionDir in directories) - { - try - { - logLocation = revisionDir + Slash.DirectorySeparatorChar + "log"; - fs = new FileStream(logLocation, FileMode.Open); - sr = new StreamReader(fs); - logMessage = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - revisionDict.Add(revisionDir, logMessage); - } - catch (Exception) - { - } - } - - return revisionDict; - } - - public int NumOfRegionRev(UUID regionid) - { - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - m_log.Info("[FSDB]: Reading scene dir: " + scenedir); - string[] directories = Directory.GetDirectories(scenedir); - return directories.Length; - } - - // Run once and only once. - public void PostInitialise() - { - SetupSerialiser(); - - m_log.Info("[FSDB]: Creating repository in " + m_repodir + "."); - CreateDirectory(); - } - - public void SaveRegion(UUID regionid, string regionName, string logMessage) - { - m_log.Info("[FSDB]: ..............................."); - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - - m_log.Info("[FSDB]: checking if scene directory exists: " + scenedir); - if (!Directory.Exists(scenedir)) - Directory.CreateDirectory(scenedir); - - int newRevisionNum = GetMostRecentRevision(regionid)+1; - string revisiondir = scenedir + newRevisionNum + Slash.DirectorySeparatorChar; - - m_log.Info("[FSDB]: checking if revision directory exists: " + revisiondir); - if (!Directory.Exists(revisiondir)) - Directory.CreateDirectory(revisiondir); - - try { - Stopwatch x = new Stopwatch(); - x.Start(); - if (m_scenes.ContainsKey(regionid)) - { - m_serialiser[regionid].SerialiseRegion(m_scenes[regionid], revisiondir); - } - x.Stop(); - TimeToSave += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk for " + regionName + ": " + x.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk so far: " + TimeToSave); - } - catch (Exception e) - { - m_log.ErrorFormat("[FSDB]: Serialisation of region failed: " + e); - return; - } - - try { - // Finish by writing log message. - FileStream file = new FileStream(revisiondir + "log", FileMode.Create, FileAccess.ReadWrite); - StreamWriter sw = new StreamWriter(file); - sw.Write(logMessage); - sw.Close(); - } - catch (Exception e) - { - m_log.ErrorFormat("[FSDB]: Failed trying to save log file " + e); - return; - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs deleted file mode 100644 index 80a0a939d9..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs +++ /dev/null @@ -1,167 +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. - */ - -#region Header - -// GitDatabase.cs -// -// -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.IO; -using Slash = System.IO.Path; -using System.Reflection; -using System.Xml; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - /// - /// Just a stub :-( - /// - public class GitDatabase : IContentDatabase - { - #region Constructors - - public GitDatabase() - { - } - - #endregion Constructors - - #region Public Methods - - public SceneObjectGroup GetMostRecentObjectRevision(UUID id) - { - return null; - } - - public int GetMostRecentRevision(UUID regionid) - { - return 0; - } - - public SceneObjectGroup GetObjectRevision(UUID id, int revision) - { - return null; - } - - public System.Collections.ArrayList GetObjectsFromRegion(UUID regionid, int revision) - { - return null; - } - - public string GetRegionObjectHeightMap(UUID regionid) - { - return null; - } - - public string GetRegionObjectHeightMap(UUID regionid, int revision) - { - return null; - } - - public string GetRegionObjectXML(UUID regionid) - { - return null; - } - - public string GetRegionObjectXML(UUID regionid, int revision) - { - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) - { - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) - { - return null; - } - - public bool InRepository(UUID id) - { - return false; - } - - public void Initialise(Scene scene, String dir) - { - } - - public System.Collections.Generic.SortedDictionary ListOfObjectRevisions(UUID id) - { - return null; - } - - public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID id) - { - return null; - } - - public int NumOfObjectRev(UUID id) - { - return 0; - } - - public int NumOfRegionRev(UUID regionid) - { - return 0; - } - - public void PostInitialise() - { - } - - public void SaveObject(SceneObjectGroup entity) - { - } - - public void SaveRegion(UUID regionid, string regionName, string logMessage) - { - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs deleted file mode 100644 index fc1f1156ca..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs +++ /dev/null @@ -1,94 +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. - */ - -#region Header - -// IContentDatabase.cs -// User: bongiojp -// -// -// - -#endregion Header - -using System; -using OpenMetaverse; -using OpenSim.Region.Framework.Scenes; -using Nini.Config; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public interface IContentDatabase - { - #region Methods - - /// - /// Returns the most recent revision number of a region. - /// - int GetMostRecentRevision(UUID regionid); - - string GetRegionObjectHeightMap(UUID regionid); - - string GetRegionObjectHeightMap(UUID regionid, int revision); - - /// - /// Retrieves the xml that describes each individual object from the last revision or specific revision of the given region. - /// - System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid); - - System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision); - - /// - /// Similar to the IRegionModule function. This is the function to be called before attempting to interface with the database. - /// Initialise should be called one for each region to be contained in the database. The directory should be the full path - /// to the repository and will only be defined once, regardless of how many times the method is called. - /// - void Initialise(Scene scene, String dir); - - /// - /// Returns a list of the revision numbers and corresponding log messages for a given region. - /// - System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID id); - - /// - /// Returns the total number of revisions saved for a specific region. - /// - int NumOfRegionRev(UUID regionid); - - /// - /// Should be called once after Initialise has been called. - /// - void PostInitialise(); - - /// - /// Saves the Region terrain map and objects within the region as xml to the database. - /// - void SaveRegion(UUID regionid, string regionName, string logMessage); - - #endregion Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs deleted file mode 100644 index c7b1ed79cc..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs +++ /dev/null @@ -1,270 +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 System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class MetaEntity - { - #region Constants - - public const float INVISIBLE = .95f; - - // Settings for transparency of metaentity - public const float NONE = 0f; - public const float TRANSLUCENT = .5f; - - #endregion Constants - - #region Static Fields - - //private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - protected SceneObjectGroup m_Entity = null; // The scene object group that represents this meta entity. - protected uint m_metaLocalid; - - #endregion Fields - - #region Constructors - - public MetaEntity() - { - } - - /// - /// Makes a new meta entity by copying the given scene object group. - /// The physics boolean is just a stub right now. - /// - public MetaEntity(SceneObjectGroup orig, bool physics) - { - m_Entity = orig.Copy(false); - Initialize(physics); - } - - /// - /// Takes an XML description of a scene object group and converts it to a meta entity. - /// - public MetaEntity(string objectXML, Scene scene, bool physics) - { - m_Entity = SceneObjectSerializer.FromXml2Format(objectXML); - m_Entity.SetScene(scene); - Initialize(physics); - } - - #endregion Constructors - - #region Public Properties - - public SceneObjectPart[] Parts - { - get { return m_Entity.Parts; } - } - - public uint LocalId - { - get { return m_Entity.LocalId; } - set { m_Entity.LocalId = value; } - } - - public SceneObjectGroup ObjectGroup - { - get { return m_Entity; } - } - - public int PrimCount - { - get { return m_Entity.PrimCount; } - } - - public SceneObjectPart RootPart - { - get { return m_Entity.RootPart; } - } - - public Scene Scene - { - get { return m_Entity.Scene; } - } - - public UUID UUID - { - get { return m_Entity.UUID; } - set { m_Entity.UUID = value; } - } - - #endregion Public Properties - - #region Protected Methods - - // The metaentity objectgroup must have unique localids as well as unique uuids. - // localids are used by the client to refer to parts. - // uuids are sent to the client and back to the server to identify parts on the server side. - /// - /// Changes localids and uuids of m_Entity. - /// - protected void Initialize(bool physics) - { - //make new uuids - Dictionary parts = new Dictionary(); - - foreach (SceneObjectPart part in m_Entity.Parts) - { - part.ResetIDs(part.LinkNum); - parts.Add(part.UUID, part); - } - - //finalize - m_Entity.RootPart.PhysActor = null; - foreach (SceneObjectPart part in parts.Values) - m_Entity.AddPart(part); - } - - #endregion Protected Methods - - #region Public Methods - - /// - /// Hides the metaentity from a single client. - /// - public virtual void Hide(IClientAPI client) - { - //This deletes the group without removing from any databases. - //This is important because we are not IN any database. - //m_Entity.FakeDeleteGroup(); - foreach (SceneObjectPart part in m_Entity.Parts) - client.SendKillObject(m_Entity.RegionHandle, part.LocalId); - } - - /// - /// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server. - /// - public virtual void HideFromAll() - { - foreach (SceneObjectPart part in m_Entity.Parts) - { - m_Entity.Scene.ForEachClient( - delegate(IClientAPI controller) - { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } - ); - } - } - - public void SendFullUpdate(IClientAPI client) - { - // Not sure what clientFlags should be but 0 seems to work - SendFullUpdate(client, 0); - } - - public void SendFullUpdate(IClientAPI client, uint clientFlags) - { - m_Entity.SendFullUpdateToClient(client); - } - - public void SendFullUpdateToAll() - { - m_Entity.Scene.ForEachClient( - delegate(IClientAPI controller) - { m_Entity.SendFullUpdateToClient(controller); } - ); - } - - /// - /// Makes a single SceneObjectPart see through. - /// - /// - /// A - /// The part to make see through - /// - /// - /// A - /// The degree of transparency to imbue the part with, 0f being solid and .95f being invisible. - /// - public static void SetPartTransparency(SceneObjectPart part, float transparencyAmount) - { - Primitive.TextureEntry tex = null; - Color4 texcolor; - try - { - tex = part.Shape.Textures; - texcolor = new Color4(); - } - catch(Exception) - { - //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing textures of scene object: " + e); - return; - } - - for (uint i = 0; i < tex.FaceTextures.Length; i++) - { - try { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.A = transparencyAmount; - tex.FaceTextures[i].RGBA = texcolor; - } - } - catch (Exception) - { - //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing different face textures of object: " + e); - continue; - } - } - try { - texcolor = tex.DefaultTexture.RGBA; - texcolor.A = transparencyAmount; - tex.DefaultTexture.RGBA = texcolor; - part.Shape.TextureEntry = tex.GetBytes(); - } - catch (Exception) - { - //m_log.Info("[Content Management]: Exception thrown while accessing default face texture of object: " + e); - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs deleted file mode 100644 index 2c5093f58d..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs +++ /dev/null @@ -1,104 +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 System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class PointMetaEntity : MetaEntity - { - #region Constructors - - public PointMetaEntity(Scene scene, Vector3 groupPos, float transparency) - : base() - { - CreatePointEntity(scene, UUID.Random(), groupPos); - SetPartTransparency(m_Entity.RootPart, transparency); - } - - public PointMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency) - : base() - { - CreatePointEntity(scene, uuid, groupPos); - SetPartTransparency(m_Entity.RootPart, transparency); - } - - #endregion Constructors - - #region Private Methods - - private void CreatePointEntity(Scene scene, UUID uuid, Vector3 groupPos) - { - SceneObjectPart y = new SceneObjectPart(); - - //Initialize part - y.Name = "Very Small Point"; - y.RegionHandle = scene.RegionInfo.RegionHandle; - y.CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; - y.OwnerID = UUID.Zero; - y.CreatorID = UUID.Zero; - y.LastOwnerID = UUID.Zero; - y.UUID = uuid; - - y.Shape = PrimitiveBaseShape.CreateBox(); - y.Scale = new Vector3(0.01f,0.01f,0.01f); - y.LastOwnerID = UUID.Zero; - y.GroupPosition = groupPos; - y.OffsetPosition = Vector3.Zero; - y.RotationOffset = Quaternion.Identity; - y.Velocity = Vector3.Zero; - y.AngularVelocity = Vector3.Zero; - y.Acceleration = Vector3.Zero; - - y.Flags = 0; - y.TrimPermissions(); - - //Initialize group and add part as root part - SceneObjectGroup x = new SceneObjectGroup(y); - x.SetScene(scene); - x.RegionHandle = scene.RegionInfo.RegionHandle; - x.SetScene(scene); - - m_Entity = x; - } - - #endregion Private Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/README b/OpenSim/Region/OptionalModules/ContentManagementSystem/README deleted file mode 100644 index 1a69fef231..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/README +++ /dev/null @@ -1,52 +0,0 @@ -This module is meant to be built alone and not added to the Opensim code base. References are made to required dlls through a -reference file, ContentManagement.mdp. Originally, for development, this project was contained in the Opensim/Region/Modules/ -directory. - -To compile: nant -To use: Copy ContentManagement.dll into the bin directory of your Opensim build. You should find many other dlls in the same directory. - - --------------------------------------------------------------------------------------------------------------------- -To build the libgit.so file: - -#Download GIT git repository -$ git clone git://git2.kernel.org/pub/OpenSim/Region/Environment/Modules/ContentManagementSystem/scm/git/git.git -$ cd git - -#Compile GIT -#Note that we are adding two extra flags to pass to gcc while compiling (-c and -fPIC) -$ autoconf -$ ./configure -$ CFLAGS="-g -O2 -Wall -c -fPIC" make - -#Copy necessary object files (and some not so necessary) to their own directory for shared object file creation -$ mkdir ../libgit-objects -$ cp builtin*.o ../libgit-objects -$ cp xdiff/*.o ../libgit-objects -$ cp libgit.a ../libgit-objects - -#Remove the main symbol from any object files (like git.o) -$ cd ../libgit-objects -$ strip -N main *.o - -#Uncompress the plumbing objects from archive created by git -$ ar x libgit.a - -#Create shared object file from all objects (including the zlib library) -$ ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o - - -#You can also just copy the following commands into a file and run as a script inside the git directory - -make clean -autoconf -./configure -CFLAGS="-g -O2 -Wall -c -fPIC" make -mkdir libgit-objects -cp builtin*.o libgit-objects -cp xdiff/*.o libgit-objects -cp libgit.a libgit-objects -cd libgit-objects -strip -N main *.o -ar x libgit.a -ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs deleted file mode 100644 index a6afa5ac74..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs +++ /dev/null @@ -1,216 +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. - */ - -#region Header - -// SceneObjectGroupDiff.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - #region Enumerations - - [Flags] - public enum Diff - { - NONE = 0, - FACECOLOR = 1, - SHAPE = 1<<1, - MATERIAL = 1<<2, - TEXTURE = 1<<3, - SCALE = 1<<4, - POSITION = 1<<5, - OFFSETPOSITION = 1<<6, - ROTATIONOFFSET = 1<<7, - ROTATIONALVELOCITY = 1<<8, - ACCELERATION = 1<<9, - ANGULARVELOCITY = 1<<10, - VELOCITY = 1<<11, - OBJECTOWNER = 1<<12, - PERMISSIONS = 1<<13, - DESCRIPTION = 1<<14, - NAME = 1<<15, - SCRIPT = 1<<16, - CLICKACTION = 1<<17, - PARTICLESYSTEM = 1<<18, - GLOW = 1<<19, - SALEPRICE = 1<<20, - SITNAME = 1<<21, - SITTARGETORIENTATION = 1<<22, - SITTARGETPOSITION = 1<<23, - TEXT = 1<<24, - TOUCHNAME = 1<<25 - } - - #endregion Enumerations - - public static class Difference - { - #region Static Fields - - static float TimeToDiff = 0; -// private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Private Methods - - private static bool AreQuaternionsEquivalent(Quaternion first, Quaternion second) - { - Vector3 firstVector = llRot2Euler(first); - Vector3 secondVector = llRot2Euler(second); - return AreVectorsEquivalent(firstVector, secondVector); - } - - private static bool AreVectorsEquivalent(Vector3 first, Vector3 second) - { - if (TruncateSignificant(first.X, 2) == TruncateSignificant(second.X, 2) - && TruncateSignificant(first.Y, 2) == TruncateSignificant(second.Y, 2) - && TruncateSignificant(first.Z, 2) == TruncateSignificant(second.Z, 2) - ) - return true; - else - return false; - } - - // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs - private static double NormalizeAngle(double angle) - { - angle = angle % (Math.PI * 2); - if (angle < 0) angle = angle + Math.PI * 2; - return angle; - } - - private static int TruncateSignificant(float num, int digits) - { - return (int) Math.Ceiling((Math.Truncate(num * 10 * digits)/10*digits)); - // return (int) ((num * (10*digits))/10*digits); - } - - // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs - // Also changed the original function from LSL_Types to LL types - private static Vector3 llRot2Euler(Quaternion r) - { - Quaternion t = new Quaternion(r.X * r.X, r.Y * r.Y, r.Z * r.Z, r.W * r.W); - double m = (t.X + t.Y + t.Z + t.W); - if (m == 0) return new Vector3(); - double n = 2 * (r.Y * r.W + r.X * r.Z); - double p = m * m - n * n; - if (p > 0) - return new Vector3((float)NormalizeAngle(Math.Atan2(2.0 * (r.X * r.W - r.Y * r.Z), (-t.X - t.Y + t.Z + t.W))), - (float)NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))), - (float)NormalizeAngle(Math.Atan2(2.0 * (r.Z * r.W - r.X * r.Y), (t.X - t.Y - t.Z + t.W)))); - else if (n > 0) - return new Vector3(0.0f, (float)(Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); - else - return new Vector3(0.0f, (float)(-Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); - } - - #endregion Private Methods - - #region Public Methods - - /// - /// Compares the attributes (Vectors, Quaternions, Strings, etc.) between two scene object parts - /// and returns a Diff bitmask which details what the differences are. - /// - public static Diff FindDifferences(SceneObjectPart first, SceneObjectPart second) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - Diff result = 0; - - // VECTOR COMPARISONS - if (!AreVectorsEquivalent(first.Acceleration, second.Acceleration)) - result |= Diff.ACCELERATION; - if (!AreVectorsEquivalent(first.AbsolutePosition, second.AbsolutePosition)) - result |= Diff.POSITION; - if (!AreVectorsEquivalent(first.AngularVelocity, second.AngularVelocity)) - result |= Diff.ANGULARVELOCITY; - if (!AreVectorsEquivalent(first.OffsetPosition, second.OffsetPosition)) - result |= Diff.OFFSETPOSITION; - if (!AreVectorsEquivalent(first.Scale, second.Scale)) - result |= Diff.SCALE; - if (!AreVectorsEquivalent(first.Velocity, second.Velocity)) - result |= Diff.VELOCITY; - - - // QUATERNION COMPARISONS - if (!AreQuaternionsEquivalent(first.RotationOffset, second.RotationOffset)) - result |= Diff.ROTATIONOFFSET; - - - // MISC COMPARISONS (UUID, Byte) - if (first.ClickAction != second.ClickAction) - result |= Diff.CLICKACTION; - if (first.OwnerID != second.OwnerID) - result |= Diff.OBJECTOWNER; - - - // STRING COMPARISONS - if (first.Description != second.Description) - result |= Diff.DESCRIPTION; - if (first.Material != second.Material) - result |= Diff.MATERIAL; - if (first.Name != second.Name) - result |= Diff.NAME; - if (first.SitName != second.SitName) - result |= Diff.SITNAME; - if (first.Text != second.Text) - result |= Diff.TEXT; - if (first.TouchName != second.TouchName) - result |= Diff.TOUCHNAME; - - x.Stop(); - TimeToDiff += x.ElapsedMilliseconds; - //m_log.Info("[DIFFERENCES] Time spent diffing objects so far" + TimeToDiff); - - return result; - } - - #endregion Public Methods - } -} From 78e76bba3825197b12e0796f3431d96909a32b0a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 5 Jun 2011 18:50:21 -0700 Subject: [PATCH 128/186] Removed unused dependency (that happened to have the wrong path) --- prebuild.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/prebuild.xml b/prebuild.xml index 0bdd14db43..90f451d6a7 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1582,7 +1582,6 @@ - From 6861606b6d8000aaa8f54a91de43f1ef05267974 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 5 Jun 2011 19:46:29 -0700 Subject: [PATCH 129/186] Narrow down the exception catching to exactly the exception of interest. This may decrease the time of processing prims with broken user data. --- .../Framework/UserManagement/UserManagementModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index f721195ccf..9051194409 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -285,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement Uri uri = new Uri(parts[0]); user.LastName = "@" + uri.Authority; } - catch + catch (UriFormatException) { m_log.DebugFormat("[SCENE]: Unable to parse Uri {0}", parts[0]); user.LastName = "@unknown"; From e77ca65e575e4f8f7645aec879b73b87ba505f49 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 6 Jun 2011 17:46:34 -0700 Subject: [PATCH 130/186] This should make offline IMs work again. It should work for incoming foreign IMs where the local recipient is offline. I can't test any of this, because I don't run an offline IM server. --- .../InstantMessage/HGMessageTransferModule.cs | 5 +- .../HGInstantMessageService.cs | 51 +++++++++++++++++-- bin/Robust.HG.ini.example | 23 +++++++-- 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs index 4de197e10d..dee86df6d2 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs @@ -213,7 +213,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } } } - result(success); + if (!success && !foreigner) + HandleUndeliveredMessage(im, result); + else + result(success); }); return; diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index 4f68e551d1..66cf4de845 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -67,6 +67,10 @@ namespace OpenSim.Services.HypergridService protected static Dictionary m_UserLocationMap = new Dictionary(); private static ExpiringCache m_RegionCache; + private static string m_RestURL; + private static bool m_ForwardOfflineGroupMessages; + private static bool m_InGatekeeper; + public HGInstantMessageService(IConfigSource config) : this(config, null) { @@ -81,8 +85,6 @@ namespace OpenSim.Services.HypergridService { m_Initialized = true; - m_log.DebugFormat("[HG IM SERVICE]: Starting..."); - IConfig serverConfig = config.Configs["HGInstantMessageService"]; if (serverConfig == null) throw new Exception(String.Format("No section HGInstantMessageService in config file")); @@ -90,6 +92,9 @@ namespace OpenSim.Services.HypergridService string gridService = serverConfig.GetString("GridService", String.Empty); string presenceService = serverConfig.GetString("PresenceService", String.Empty); string userAgentService = serverConfig.GetString("UserAgentService", String.Empty); + m_InGatekeeper = serverConfig.GetBoolean("InGatekeeper", false); + m_log.DebugFormat("[HG IM SERVICE]: Starting... InRobust? {0}", m_InGatekeeper); + if (gridService == string.Empty || presenceService == string.Empty) throw new Exception(String.Format("Incomplete specifications, InstantMessage Service cannot function.")); @@ -101,6 +106,21 @@ namespace OpenSim.Services.HypergridService m_RegionCache = new ExpiringCache(); + IConfig cnf = config.Configs["Messaging"]; + if (cnf == null) + { + return; + } + + m_RestURL = cnf.GetString("OfflineMessageURL", string.Empty); + if (m_RestURL == string.Empty) + { + m_log.Error("[HG IM SERVICE]: Offline IMs enabled, but no URL is given"); + return; + } + + m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", false); + } } @@ -109,13 +129,21 @@ namespace OpenSim.Services.HypergridService m_log.DebugFormat("[HG IM SERVICE]: Received message from {0} to {1}", im.fromAgentID, im.toAgentID); UUID toAgentID = new UUID(im.toAgentID); + bool success = false; if (m_IMSimConnector != null) { //m_log.DebugFormat("[XXX] SendIMToRegion local im connector"); - return m_IMSimConnector.SendInstantMessage(im); + success = m_IMSimConnector.SendInstantMessage(im); } else - return TrySendInstantMessage(im, "", true, false); + { + success = TrySendInstantMessage(im, "", true, false); + } + + if (!success && m_InGatekeeper) // we do this only in the Gatekeeper IM service + UndeliveredMessage(im); + + return success; } public bool OutgoingInstantMessage(GridInstantMessage im, string url, bool foreigner) @@ -129,6 +157,7 @@ namespace OpenSim.Services.HypergridService upd.RegionID = UUID.Zero; return TrySendInstantMessage(im, upd, true, foreigner); } + } protected bool TrySendInstantMessage(GridInstantMessage im, object previousLocation, bool firstTime, bool foreigner) @@ -313,5 +342,19 @@ namespace OpenSim.Services.HypergridService } } + + private bool UndeliveredMessage(GridInstantMessage im) + { + if (m_RestURL != string.Empty && (im.offline != 0) + && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages))) + { + return SynchronousRestObjectPoster.BeginPostObject( + "POST", m_RestURL + "/SaveMessage/", im); + + } + + else + return false; + } } } diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 7b2f8acd33..812d2659fa 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -356,8 +356,23 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" [HGInstantMessageService] - LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" - GridService = "OpenSim.Services.GridService.dll:GridService" - PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" - UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.GridService.dll:GridService" + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + ; This should always be true in the Robust config + InGatekeeper = True + +[Messaging] + ; If you have an Offline IM server, set the vars in this section, so that + ; incomming IMs to local users from foreign grids can be saved + ; + ;# {OfflineMessageURL} {OfflineMessageModule:OfflineMessageModule} {URL of offline messaging service} {} + ;; URL of web service for offline message storage + ; OfflineMessageURL = http://yourserver/Offline.php + + ;; Control whether group messages are forwarded to offline users. + ;; Default is true. + ;; This applies to the core groups module (Flotsam) only. + ; ForwardOfflineGroupMessages = true From dce0e46eaa8c8f7f9a0fc99697cc78a3f561b3c3 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 6 Jun 2011 18:20:02 -0700 Subject: [PATCH 131/186] Moved the Mono Addins declaration of the HGFriendsModule to where the one for FriendModule is -- CoreModulePlugin.addin.xml (trying to hunt down the slowness reported by Nebadon related to HGFriends) --- OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs | 1 - OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index b0a75674e6..f6f0e89115 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -45,7 +45,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Region.CoreModules.Avatar.Friends { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index 8a6735f378..e22fd38107 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -24,6 +24,7 @@ + From 1a23d322ace6001130db24d11962850b333c8399 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 6 Jun 2011 19:52:50 -0700 Subject: [PATCH 132/186] More on the hunt for the slow down on HGFriendsModule. - Don't requests the online friends on foreign grids. If this works, there's another way of getting that info. --- .../Avatar/Friends/HGFriendsModule.cs | 119 +++++++++++------- 1 file changed, 71 insertions(+), 48 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index f6f0e89115..ddf9289362 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -87,25 +87,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (base.FetchFriendslist(client)) { UUID agentID = client.AgentId; - // We need to preload the user management cache with the names - // of foreign friends, just like we do with SOPs' creators - foreach (FriendInfo finfo in m_Friends[agentID].Friends) + // we do this only for the root agent + if (m_Friends[agentID].Refcount == 1) { - if (finfo.TheirFlags != -1) + // We need to preload the user management cache with the names + // of foreign friends, just like we do with SOPs' creators + foreach (FriendInfo finfo in m_Friends[agentID].Friends) { - UUID id; - if (!UUID.TryParse(finfo.Friend, out id)) + if (finfo.TheirFlags != -1) { - string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; - if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp)) + UUID id; + if (!UUID.TryParse(finfo.Friend, out id)) { - IUserManagement uMan = m_Scenes[0].RequestModuleInterface(); - uMan.AddUser(id, url + ";" + first + " " + last); + string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp)) + { + IUserManagement uMan = m_Scenes[0].RequestModuleInterface(); + uMan.AddUser(id, url + ";" + first + " " + last); + } } } } + return true; } - return true; } return false; } @@ -114,13 +118,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { if (base.SendFriendsOnlineIfNeeded(client)) { - UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId); - if (account == null) // foreign + AgentCircuitData aCircuit = ((Scene)client.Scene).AuthenticateHandler.GetAgentCircuitData(client.AgentId); + if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) { - FriendInfo[] friends = GetFriends(client.AgentId); - foreach (FriendInfo f in friends) + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId); + if (account == null) // foreign { - client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags); + FriendInfo[] friends = GetFriends(client.AgentId); + foreach (FriendInfo f in friends) + { + client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags); + } } } } @@ -129,48 +137,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends protected override void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) { - // Let's single out the UUIs - List localFriends = new List(); - List foreignFriends = new List(); - string tmp = string.Empty; - + List fList = new List(); foreach (string s in friendList) - { - UUID id; - if (UUID.TryParse(s, out id)) - localFriends.Add(s); - else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp)) - { - foreignFriends.Add(s); - // add it here too, who knows maybe the foreign friends happens to be on this grid - localFriends.Add(id.ToString()); - } - } + fList.Add(s.Substring(0, 36)); - // OK, see who's present on this grid - List toBeRemoved = new List(); - PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray()); + PresenceInfo[] presence = PresenceService.GetAgents(fList.ToArray()); foreach (PresenceInfo pi in presence) { UUID presenceID; if (UUID.TryParse(pi.UserID, out presenceID)) - { online.Add(presenceID); - foreach (string s in foreignFriends) - if (s.StartsWith(pi.UserID)) - toBeRemoved.Add(s); - } } - - foreach (string s in toBeRemoved) - foreignFriends.Remove(s); - - // OK, let's send this up the stack, and leave a closure here - // collecting online friends in other grids - Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); }); - } + //protected override void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) + //{ + // // Let's single out the UUIs + // List localFriends = new List(); + // List foreignFriends = new List(); + // string tmp = string.Empty; + + // foreach (string s in friendList) + // { + // UUID id; + // if (UUID.TryParse(s, out id)) + // localFriends.Add(s); + // else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp)) + // { + // foreignFriends.Add(s); + // // add it here too, who knows maybe the foreign friends happens to be on this grid + // localFriends.Add(id.ToString()); + // } + // } + + // // OK, see who's present on this grid + // List toBeRemoved = new List(); + // PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray()); + // foreach (PresenceInfo pi in presence) + // { + // UUID presenceID; + // if (UUID.TryParse(pi.UserID, out presenceID)) + // { + // online.Add(presenceID); + // foreach (string s in foreignFriends) + // if (s.StartsWith(pi.UserID)) + // toBeRemoved.Add(s); + // } + // } + + // foreach (string s in toBeRemoved) + // foreignFriends.Remove(s); + + // // OK, let's send this up the stack, and leave a closure here + // // collecting online friends in other grids + // Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); }); + + //} + private void CollectOnlineFriendsElsewhere(UUID userID, List foreignFriends) { // let's divide the friends on a per-domain basis From f5d82350bb622baa6f49042882e6c5cb49b24cc0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 7 Jun 2011 10:51:12 -0700 Subject: [PATCH 133/186] This fixes the crash reported in http://opensimulator.org/mantis/view.php?id=5529 related to sending IMs to foreign friends who are offline. Hopefully. --- .../InstantMessage/HGMessageTransferModule.cs | 8 ++++-- .../Hypergrid/UserAgentServerConnector.cs | 24 ++++++++-------- .../HGInstantMessageService.cs | 28 ++++++++----------- .../HypergridService/UserAgentService.cs | 2 +- .../Services/Interfaces/IHypergridServices.cs | 2 +- bin/config-include/StandaloneHypergrid.ini | 1 + 6 files changed, 32 insertions(+), 33 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs index dee86df6d2..7753c259b3 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs @@ -196,10 +196,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage Util.FireAndForget(delegate { - bool success = m_IMService.OutgoingInstantMessage(im, url, foreigner); - if (!success && account == null) + bool success = false; + if (foreigner && url == string.Empty) // we don't know about this user { - // One last chance string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID); m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI); if (recipientUUI != string.Empty) @@ -213,6 +212,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } } } + else + success = m_IMService.OutgoingInstantMessage(im, url, foreigner); + if (!success && !foreigner) HandleUndeliveredMessage(im, result); else diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index 9961164377..2022d8a4f1 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -268,18 +268,18 @@ namespace OpenSim.Server.Handlers.Hypergrid ids.Add(requestData[key].ToString()); } - List online = m_HomeUsersService.GetOnlineFriends(userID, ids); - if (online.Count > 0) - { - int i = 0; - foreach (UUID id in online) - { - hash["friend_" + i.ToString()] = id.ToString(); - i++; - } - } - else - hash["result"] = "No Friends Online"; + //List online = m_HomeUsersService.GetOnlineFriends(userID, ids); + //if (online.Count > 0) + //{ + // int i = 0; + // foreach (UUID id in online) + // { + // hash["friend_" + i.ToString()] = id.ToString(); + // i++; + // } + //} + //else + // hash["result"] = "No Friends Online"; } XmlRpcResponse response = new XmlRpcResponse(); diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index 66cf4de845..90a0bf215f 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -185,7 +185,6 @@ namespace OpenSim.Services.HypergridService { lookupAgent = true; upd = null; - url = string.Empty; } } else @@ -221,19 +220,16 @@ namespace OpenSim.Services.HypergridService url = m_UserAgentService.LocateUser(toAgentID); } - if (upd != null || url != string.Empty) + // check if we've tried this before.. + // This is one way to end the recursive loop + // + if (!firstTime && ((previousLocation is PresenceInfo && upd != null && upd.RegionID == ((PresenceInfo)previousLocation).RegionID) || + (previousLocation is string && upd == null && previousLocation.Equals(url)))) { - // check if we've tried this before.. - // This is one way to end the recursive loop - // - if (!firstTime && ((previousLocation is PresenceInfo && upd != null && upd.RegionID == ((PresenceInfo)previousLocation).RegionID) || - (previousLocation is string && upd == null && previousLocation.Equals(url)))) - { - // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); - m_log.DebugFormat("[HG IM SERVICE]: Fail 2 {0} {1}", previousLocation, url); + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + m_log.DebugFormat("[HG IM SERVICE]: Fail 2 {0} {1}", previousLocation, url); - return false; - } + return false; } } @@ -332,10 +328,6 @@ namespace OpenSim.Services.HypergridService else { // try again, but lookup user this time. - // Warning, this must call the Async version - // of this method or we'll be making thousands of threads - // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync - // The version that spawns the thread is SendGridInstantMessageViaXMLRPC // This is recursive!!!!! return TrySendInstantMessage(im, url, false, foreigner); @@ -348,13 +340,17 @@ namespace OpenSim.Services.HypergridService if (m_RestURL != string.Empty && (im.offline != 0) && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages))) { + m_log.DebugFormat("[HG IM SERVICE]: Message saved"); return SynchronousRestObjectPoster.BeginPostObject( "POST", m_RestURL + "/SaveMessage/", im); } else + { + m_log.DebugFormat("[HG IM SERVICE]: No offline IM service, message not saved"); return false; + } } } } diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 2f2ebfba5a..8d78f97dd2 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -482,7 +482,7 @@ namespace OpenSim.Services.HypergridService { foreach (TravelingAgentInfo t in m_TravelingAgents.Values) { - if (t.UserID == userID) + if (t.UserID == userID && !m_GridName.Equals(t.GridExternalName)) return t.GridExternalName; } diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs index 82ec8ceee5..3c6fedf6af 100644 --- a/OpenSim/Services/Interfaces/IHypergridServices.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -62,7 +62,7 @@ namespace OpenSim.Services.Interfaces string GetUUI(UUID userID, UUID targetUserID); void StatusNotification(List friends, UUID userID, bool online); - List GetOnlineFriends(UUID userID, List friends); + //List GetOnlineFriends(UUID userID, List friends); bool AgentIsComingHome(UUID sessionID, string thisGridExternalName); bool VerifyAgent(UUID sessionID, string token); diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index 574375eed8..8480a77bbd 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -160,6 +160,7 @@ GridService = "OpenSim.Services.GridService.dll:GridService" PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + InGatekeeper = True ;; This should always be the very last thing on this file From 41627bdf8a98358829a6a1210cb14ba143fdeee2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 7 Jun 2011 12:09:32 -0700 Subject: [PATCH 134/186] Remove scary error message --- .../Services/HypergridService/HGInstantMessageService.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index 90a0bf215f..09dbc656f6 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -113,12 +113,6 @@ namespace OpenSim.Services.HypergridService } m_RestURL = cnf.GetString("OfflineMessageURL", string.Empty); - if (m_RestURL == string.Empty) - { - m_log.Error("[HG IM SERVICE]: Offline IMs enabled, but no URL is given"); - return; - } - m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", false); } From 02b40670be7d6c42de7235285f2e136aa6109fd3 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 7 Jun 2011 12:10:57 -0700 Subject: [PATCH 135/186] This makes the display names work better for foreigners --- OpenSim/Region/Framework/Scenes/Scene.cs | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 77301d8844..588d6275a2 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2571,12 +2571,38 @@ namespace OpenSim.Region.Framework.Scenes if (GetScenePresence(client.AgentId) != null) { m_LastLogin = Util.EnvironmentTickCount(); + + // Cache the user's name + CacheUserName(aCircuit); + EventManager.TriggerOnNewClient(client); if (vialogin) EventManager.TriggerOnClientLogin(client); } } + private void CacheUserName(AgentCircuitData aCircuit) + { + IUserManagement uMan = RequestModuleInterface(); + if (uMan != null) + { + string homeURL = string.Empty; + string first = aCircuit.firstname, last = aCircuit.lastname; + if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) + homeURL = aCircuit.ServiceURLs["HomeURI"].ToString(); + if (aCircuit.lastname.StartsWith("@")) + { + string[] parts = aCircuit.firstname.Split('.'); + if (parts.Length >= 2) + { + first = parts[0]; + last = parts[1]; + } + } + uMan.AddUser(aCircuit.AgentID, first, last, homeURL); + } + } + private bool VerifyClient(AgentCircuitData aCircuit, System.Net.IPEndPoint ep, out bool vialogin) { vialogin = false; From 3307db5d4aedec5cc31541e9a28a95abdd4999d0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 7 Jun 2011 19:36:04 -0700 Subject: [PATCH 136/186] This hopefully fixes all issues with online/offline notifications across grids. http://opensimulator.org/mantis/view.php?id=5528 --- .../Avatar/Friends/FriendsModule.cs | 2 +- .../Avatar/Friends/HGFriendsModule.cs | 11 +++- .../Hypergrid/UserAgentServerConnector.cs | 16 +++++- .../Hypergrid/UserAgentServiceConnector.cs | 55 ++++++++++++++++++- .../HypergridService/UserAgentService.cs | 28 +++++++--- .../Services/Interfaces/IHypergridServices.cs | 3 +- 6 files changed, 99 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index f82716d50f..daee4ca3fc 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -830,10 +830,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends public bool LocalStatusNotification(UUID userID, UUID friendID, bool online) { + m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online); IClientAPI friendClient = LocateClientObject(friendID); if (friendClient != null) { - //m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online); // the friend in this sim as root agent if (online) friendClient.SendAgentOnline(new UUID[] { userID }); diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index ddf9289362..b9d67193ab 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -75,7 +75,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends /// friend whose status changed /// status /// - public bool StatusNotify(UUID userID, UUID friendID, bool online) + public bool StatusNotify(UUID friendID, UUID userID, bool online) { return LocalStatusNotification(friendID, userID, online); } @@ -279,7 +279,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends foreach (FriendInfo f in kvp.Value) ids.Add(f.Friend); UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); - uConn.StatusNotification(ids, userID, online); + List friendsOnline = uConn.StatusNotification(ids, userID, online); + // need to debug this here + if (online) + { + IClientAPI client = LocateClientObject(userID); + if (client != null) + client.SendAgentOnline(friendsOnline.ToArray()); + } } } } diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index 2022d8a4f1..72a4aeaa62 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -237,10 +237,20 @@ namespace OpenSim.Server.Handlers.Hypergrid bool online = false; bool.TryParse(requestData["online"].ToString(), out online); - hash["result"] = "true"; - // let's spawn a thread for this, because it may take a long time... - Util.FireAndForget(delegate { m_HomeUsersService.StatusNotification(ids, userID, online); }); + List friendsOnline = m_HomeUsersService.StatusNotification(ids, userID, online); + if (friendsOnline.Count > 0) + { + int i = 0; + foreach (UUID id in friendsOnline) + { + hash["friend_" + i.ToString()] = id.ToString(); + i++; + } + } + else + hash["result"] = "No Friends Online"; + } XmlRpcResponse response = new XmlRpcResponse(); diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 046f755f47..853e5243ab 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -404,7 +404,7 @@ namespace OpenSim.Services.Connectors.Hypergrid GetBoolResponse(request, out reason); } - public void StatusNotification(List friends, UUID userID, bool online) + public List StatusNotification(List friends, UUID userID, bool online) { Hashtable hash = new Hashtable(); hash["userID"] = userID.ToString(); @@ -421,8 +421,59 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcRequest request = new XmlRpcRequest("status_notification", paramList); string reason = string.Empty; - GetBoolResponse(request, out reason); + // Send and get reply + List friendsOnline = new List(); + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return friendsOnline; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return friendsOnline; + } + + 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]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return friendsOnline; + } + + // Here is the actual response + foreach (object key in hash.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null) + { + UUID uuid; + if (UUID.TryParse(hash[key].ToString(), out uuid)) + friendsOnline.Add(uuid); + } + } + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); + reason = "Exception: " + e.Message; + } + + return friendsOnline; } public List GetOnlineFriends(UUID userID, List friends) diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 8d78f97dd2..29d8b3d4c9 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -324,14 +324,16 @@ namespace OpenSim.Services.HypergridService return false; } - public void StatusNotification(List friends, UUID foreignUserID, bool online) + public List StatusNotification(List friends, UUID foreignUserID, bool online) { if (m_FriendsService == null || m_PresenceService == null) { m_log.WarnFormat("[USER AGENT SERVICE]: Unable to perform status notifications because friends or presence services are missing"); - return; + return new List(); } + List localFriendsOnline = new List(); + m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: foreign user {0} wants to notify {1} local friends", foreignUserID, friends.Count); // First, let's double check that the reported friends are, indeed, friends of that user @@ -372,8 +374,12 @@ namespace OpenSim.Services.HypergridService if (friendSession != null) { - ForwardStatusNotificationToSim(friendSession.RegionID, friendSession.UserID, foreignUserID, online); + ForwardStatusNotificationToSim(friendSession.RegionID, foreignUserID, friendSession.UserID, online); usersToBeNotified.Remove(friendSession.UserID.ToString()); + UUID id; + if (UUID.TryParse(friendSession.UserID, out id)) + localFriendsOnline.Add(id); + } } @@ -388,9 +394,17 @@ namespace OpenSim.Services.HypergridService 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) + { + return localFriendsOnline; + } + else + return new List(); } - protected void ForwardStatusNotificationToSim(UUID regionID, string user, UUID foreignUserID, bool online) + protected void ForwardStatusNotificationToSim(UUID regionID, UUID foreignUserID, string user, bool online) { UUID userID; if (UUID.TryParse(user, out userID)) @@ -398,15 +412,15 @@ namespace OpenSim.Services.HypergridService if (m_FriendsLocalSimConnector != null) { m_log.DebugFormat("[USER AGENT SERVICE]: Local Notify, user {0} is {1}", foreignUserID, (online ? "online" : "offline")); - m_FriendsLocalSimConnector.StatusNotify(userID, foreignUserID, online); + m_FriendsLocalSimConnector.StatusNotify(foreignUserID, userID, online); } else { GridRegion region = m_GridService.GetRegionByUUID(UUID.Zero /* !!! */, regionID); if (region != null) { - m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, user, foreignUserID, (online ? "online" : "offline")); - m_FriendsSimConnector.StatusNotify(region, userID, foreignUserID, online); + m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline")); + m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID, online); } } } diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs index 3c6fedf6af..220caef007 100644 --- a/OpenSim/Services/Interfaces/IHypergridServices.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -61,7 +61,8 @@ namespace OpenSim.Services.Interfaces // on behalf of the userID string GetUUI(UUID userID, UUID targetUserID); - void StatusNotification(List friends, UUID userID, bool online); + // Returns the local friends online + List StatusNotification(List friends, UUID userID, bool online); //List GetOnlineFriends(UUID userID, List friends); bool AgentIsComingHome(UUID sessionID, string thisGridExternalName); From eabfc9ca153b1b9775bada56c2c0120768a77fda Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 7 Jun 2011 20:05:24 -0700 Subject: [PATCH 137/186] Added error message to help understand http://opensimulator.org/mantis/view.php?id=5527 --- OpenSim/Services/HypergridService/UserAgentService.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 29d8b3d4c9..7ed5ea5ed0 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -496,6 +496,11 @@ namespace OpenSim.Services.HypergridService { 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; } From 39323055bd205ba2bc241e3c52313d2aa4717dfe Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Wed, 25 May 2011 18:45:10 +0300 Subject: [PATCH 138/186] When a plugin fails to load because a DLL is missing, log which DLL it is --- OpenSim/Server/Base/ServerUtils.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs index 6743a2e7c8..8effdd2d1b 100644 --- a/OpenSim/Server/Base/ServerUtils.cs +++ b/OpenSim/Server/Base/ServerUtils.cs @@ -128,6 +128,13 @@ namespace OpenSim.Server.Base return null; } + catch (ReflectionTypeLoadException rtle) + { + m_log.Error(string.Format("Error loading plugin from {0}:\n{1}", dllName, + String.Join("\n", Array.ConvertAll(rtle.LoaderExceptions, e => e.ToString()))), + rtle); + return null; + } catch (Exception e) { m_log.Error(string.Format("Error loading plugin from {0}", dllName), e); From 61f1c2b2c517ccd00bf1e7c4efe9c7567c891fe0 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Thu, 26 May 2011 13:41:56 +0300 Subject: [PATCH 139/186] Write estate errors on startup to the log --- OpenSim/Region/Application/OpenSimBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index ea9edf686b..00b080c91e 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -836,7 +836,7 @@ namespace OpenSim if (regInfo.EstateSettings.EstateID == 0) // No record at all { - MainConsole.Instance.OutputFormat("Region {0} is not part of an estate.", regInfo.RegionName); + m_log.WarnFormat("[ESTATE] Region {0} is not part of an estate.", regInfo.RegionName); List estates = EstateDataService.LoadEstateSettingsAll(); List estateNames = new List(); @@ -847,7 +847,7 @@ namespace OpenSim { if (estates.Count == 0) { - MainConsole.Instance.Output("No existing estates found. You must create a new one."); + m_log.Info("[ESTATE] No existing estates found. You must create a new one."); if (CreateEstate(regInfo, estateNames)) break; From 90f657d77d2df4ff0867431a8bcf34cbed13057f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 8 Jun 2011 13:45:38 -0700 Subject: [PATCH 140/186] Deleted wrong debug message. --- OpenSim/Services/HypergridService/HGInstantMessageService.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index 09dbc656f6..ded589de2d 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -342,7 +342,6 @@ namespace OpenSim.Services.HypergridService else { - m_log.DebugFormat("[HG IM SERVICE]: No offline IM service, message not saved"); return false; } } From 9759b2a4bb5e5e2bed4c74cea05be58640c8e7c3 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 8 Jun 2011 15:18:14 -0700 Subject: [PATCH 141/186] Added EventManager.OnPrimsLoaded, an event that modules can hook up onto so that they know when the scene's objects have been loaded from the DB. --- .../Region/Framework/Scenes/EventManager.cs | 24 +++++++++++++++++++ OpenSim/Region/Framework/Scenes/Scene.cs | 1 + 2 files changed, 25 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index b43d5f06ea..b67937dfc6 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -392,6 +392,9 @@ namespace OpenSim.Region.Framework.Scenes public delegate void LoginsEnabled(string regionName); public event LoginsEnabled OnLoginsEnabled; + public delegate void PrimsLoaded(Scene s); + public event PrimsLoaded OnPrimsLoaded; + public class MoneyTransferArgs : EventArgs { public UUID sender; @@ -2242,5 +2245,26 @@ namespace OpenSim.Region.Framework.Scenes } } } + + public void TriggerPrimsLoaded(Scene s) + { + PrimsLoaded handler = OnPrimsLoaded; + + if (handler != null) + { + foreach (PrimsLoaded d in handler.GetInvocationList()) + { + try + { + d(s); + } + catch (Exception e) + { + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for PrimsLoaded failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 588d6275a2..f122b58eb3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1754,6 +1754,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.Info("[SCENE]: Loaded " + PrimsFromDB.Count.ToString() + " SceneObject(s)"); LoadingPrims = false; + EventManager.TriggerPrimsLoaded(this); } From 80fc607d7536d4f375da4d01280a00fe656654c4 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 8 Jun 2011 16:01:33 -0700 Subject: [PATCH 142/186] Fixed "Unknown User" listed as creator/owner on prims created with the Build button by foreign visitors. Added command to the UserManagementModule to list all the known bindings between user UUIDs and their names: show user-names. --- .../UserManagement/UserManagementModule.cs | 74 +++++++++++++++++-- .../Framework/Interfaces/IUserManagement.cs | 1 + OpenSim/Region/Framework/Scenes/Scene.cs | 4 + 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 9051194409..ae4336c88a 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -30,6 +30,7 @@ using System.IO; using System.Reflection; using OpenSim.Framework; +using OpenSim.Framework.Console; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; @@ -80,6 +81,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement // } // } //} + MainConsole.Instance.Commands.AddCommand("grid", true, + "show user-names", + "show user-names", + "Show the bindings between user UUIDs and user names", + String.Empty, + HandleShowUsers); + + } public bool IsSharedModule @@ -103,6 +112,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); + scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); } public void RemoveRegion(Scene scene) @@ -111,18 +121,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement m_Scenes.Remove(scene); } - public void RegionLoaded(Scene scene) + public void RegionLoaded(Scene s) { } public void PostInitialise() { - foreach (Scene s in m_Scenes) - { - // let's sniff all the user names referenced by objects in the scene - m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length); - s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); - } } public void Close() @@ -136,6 +140,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement #region Event Handlers + void EventManager_OnPrimsLoaded(Scene s) + { + // let's sniff all the user names referenced by objects in the scene + m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length); + s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); + } + + void EventManager_OnNewClient(IClientAPI client) { client.OnNameFromUUIDRequest += new UUIDNameRequest(HandleUUIDNameRequest); @@ -143,7 +155,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) { - //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0}", uuid); if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) { remote_client.SendNameReply(uuid, "Mr", "OpenSim"); @@ -153,6 +164,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement string[] names = GetUserNames(uuid); if (names.Length == 2) { + //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]); remote_client.SendNameReply(uuid, names[0], names[1]); } @@ -254,6 +266,32 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement return string.Empty; } + public string GetUserUUI(UUID userID) + { + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID); + if (account != null) + return userID.ToString(); + + if (m_UserCache.ContainsKey(userID)) + { + UserData ud = m_UserCache[userID]; + string homeURL = ud.HomeURL; + string first = ud.FirstName, last = ud.LastName; + if (ud.LastName.StartsWith("@")) + { + string[] parts = ud.FirstName.Split('.'); + if (parts.Length >= 2) + { + first = parts[0]; + last = parts[1]; + } + return userID + ";" + homeURL + ";" + first + " " + last; + } + } + + return userID.ToString(); + } + public void AddUser(UUID id, string creatorData) { if (m_UserCache.ContainsKey(id)) @@ -343,5 +381,25 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement //} #endregion IUserManagement + + private void HandleShowUsers(string module, string[] cmd) + { + if (m_UserCache.Count == 0) + { + MainConsole.Instance.Output("No users not found"); + return; + } + + MainConsole.Instance.Output("UUID User Name"); + MainConsole.Instance.Output("-----------------------------------------------------------------------------"); + foreach (KeyValuePair kvp in m_UserCache) + { + MainConsole.Instance.Output(String.Format("{0} {1} {2}", + kvp.Key, kvp.Value.FirstName, kvp.Value.LastName)); + } + return; + } + + } } diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs index 9cac3b061a..5d30aa8e24 100644 --- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs +++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs @@ -9,6 +9,7 @@ namespace OpenSim.Region.Framework.Interfaces { string GetUserName(UUID uuid); string GetUserHomeURL(UUID uuid); + string GetUserUUI(UUID uuid); string GetUserServerURL(UUID uuid, string serverType); void AddUser(UUID uuid, string userData); void AddUser(UUID uuid, string firstName, string lastName, string profileURL); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f122b58eb3..bdf3d1dcd8 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1910,6 +1910,10 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.SetGroup(groupID, null); } + IUserManagement uman = RequestModuleInterface(); + if (uman != null) + sceneObject.RootPart.CreatorIdentification = uman.GetUserUUI(ownerID); + sceneObject.ScheduleGroupForFullUpdate(); return sceneObject; From 1bd712c541bb4f26a0547f5ae463092c21997713 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 8 Jun 2011 16:12:47 -0700 Subject: [PATCH 143/186] Reverting the [HG]MapModule to its buggy behavior above 4096. Ppl seem to prefer the color blue, and I have given up trying to make things work above 4096. Revert "Improved reuse on the WorldMap/WorldMapModule.cs" This reverts commit d473d9975e70366d0fd16276c9bafd5ec269dcd9. --- .../World/WorldMap/WorldMapModule.cs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 10e1631a1a..0cacf2dce1 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -233,8 +233,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } if (lookup) { - List mapBlocks = GetAndSendBlocks(avatarPresence.ControllingClient, (int)(m_scene.RegionInfo.RegionLocX) - 4, (int)(m_scene.RegionInfo.RegionLocY) - 4, - (int)(m_scene.RegionInfo.RegionLocX) + 4, (int)(m_scene.RegionInfo.RegionLocY) + 4, 0); + List mapBlocks = new List(); ; + + List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, + (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); + foreach (GridRegion r in regions) + { + MapBlockData block = new MapBlockData(); + MapBlockFromGridRegion(block, r); + mapBlocks.Add(block); + } + avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); lock (cachedMapBlocks) cachedMapBlocks = mapBlocks; @@ -820,7 +832,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } } - protected virtual List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + protected virtual void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, @@ -835,8 +847,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap mapBlocks.Add(block); } remoteClient.SendMapBlock(mapBlocks, 0); - - return mapBlocks; } protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r) From 2a46f756d673f4caa2049f2ddda219fdba810eed Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 8 Jun 2011 16:38:25 -0700 Subject: [PATCH 144/186] Fixed a compilation problem. Also added a lengthy comment on the Map hack, so that it never goes unnoticed again. --- .../CoreModules/Hypergrid/HGWorldMapModule.cs | 3 +- .../World/WorldMap/WorldMapModule.cs | 87 +++++++++++-------- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs index 0781de0485..f066f83540 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs @@ -59,7 +59,7 @@ namespace OpenSim.Region.CoreModules.Hypergrid #endregion - protected override List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + protected override void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, @@ -96,7 +96,6 @@ namespace OpenSim.Region.CoreModules.Hypergrid remoteClient.SendMapBlock(mapBlocks, 0); - return mapBlocks; } diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 0cacf2dce1..ed3677bf45 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -208,52 +208,65 @@ namespace OpenSim.Region.CoreModules.World.WorldMap //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}", // path, param, agentID.ToString()); - // this is here because CAPS map requests work even beyond the 10,000 limit. - ScenePresence avatarPresence = null; + // There is a major hack going on in this method. The viewer doesn't request + // map blocks (RequestMapBlocks) above 4096. That means that if we don't hack, + // grids above that cell don't have a map at all. So, here's the hack: we wait + // for this CAP request to come, and we inject the map blocks at this point. + // In a normal scenario, this request simply sends back the MapLayer (the blue color). + // In the hacked scenario, it also sends the map blocks via UDP. + // + // 6/8/2011 -- I'm adding an explicit 4096 check, so that we never forget that there is + // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. - m_scene.TryGetScenePresence(agentID, out avatarPresence); - - if (avatarPresence != null) + if (m_scene.RegionInfo.RegionLocX >= 4096 || m_scene.RegionInfo.RegionLocY > 4096) { - bool lookup = false; + ScenePresence avatarPresence = null; - lock (cachedMapBlocks) + m_scene.TryGetScenePresence(agentID, out avatarPresence); + + if (avatarPresence != null) { - if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) - { - List mapBlocks; - - mapBlocks = cachedMapBlocks; - avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); - } - else - { - lookup = true; - } - } - if (lookup) - { - List mapBlocks = new List(); ; - - List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); - foreach (GridRegion r in regions) - { - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r); - mapBlocks.Add(block); - } - avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + bool lookup = false; lock (cachedMapBlocks) - cachedMapBlocks = mapBlocks; + { + if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) + { + List mapBlocks; - cachedTime = Util.UnixTimeSinceEpoch(); + mapBlocks = cachedMapBlocks; + avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + } + else + { + lookup = true; + } + } + if (lookup) + { + List mapBlocks = new List(); ; + + List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, + (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); + foreach (GridRegion r in regions) + { + MapBlockData block = new MapBlockData(); + MapBlockFromGridRegion(block, r); + mapBlocks.Add(block); + } + avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + + lock (cachedMapBlocks) + cachedMapBlocks = mapBlocks; + + cachedTime = Util.UnixTimeSinceEpoch(); + } } } + LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); return mapResponse.ToString(); From 49e4e5392899a274e9c05d00e8abba35d3c25b02 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 8 Jun 2011 16:41:58 -0700 Subject: [PATCH 145/186] Consistency fix on the last commit. --- OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index ed3677bf45..30cf1dba39 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -218,7 +218,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap // 6/8/2011 -- I'm adding an explicit 4096 check, so that we never forget that there is // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. - if (m_scene.RegionInfo.RegionLocX >= 4096 || m_scene.RegionInfo.RegionLocY > 4096) + if (m_scene.RegionInfo.RegionLocX >= 4096 || m_scene.RegionInfo.RegionLocY >= 4096) { ScenePresence avatarPresence = null; From 4cf60c5d9d95b5d7566c24f79f321e39fc2e2679 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 8 Jun 2011 19:51:48 -0700 Subject: [PATCH 146/186] Removing special casing on failures. This may also fix reports of this issue: 22:07:53 - [USER AGENT CONNECTOR]: remote call to http://hg.osgrid.org:80/ returned an error: Requested method [locate_user] from 127.0.0.1 threw exception: Object reference not set to an instance of an object at OpenSim.Services.HypergridService.UserAgentService.LocateUser (UUID userID) [0x00000] in :0 --- OpenSim/Services/HypergridService/UserAgentService.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 7ed5ea5ed0..1559cf3205 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -197,9 +197,11 @@ namespace OpenSim.Services.HypergridService agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason); // restore the old travel info - if(reason != "Logins Disabled") + lock (m_TravelingAgents) { - lock (m_TravelingAgents) + if (old == null) + m_TravelingAgents.Remove(agentCircuit.SessionID); + else m_TravelingAgents[agentCircuit.SessionID] = old; } From e3e1f6308d4636b546798f6aa2f7624b8dc52c9e Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 9 Jun 2011 16:11:47 -0700 Subject: [PATCH 147/186] Change the name of the newest command to "show names" so that it doesn't conflict with the existing "show users" --- .../Framework/UserManagement/UserManagementModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index ae4336c88a..accd09443c 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -82,8 +82,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement // } //} MainConsole.Instance.Commands.AddCommand("grid", true, - "show user-names", - "show user-names", + "show names", + "show names", "Show the bindings between user UUIDs and user names", String.Empty, HandleShowUsers); From 8d3a8a0a8150e856103a152228b736ab74f821d7 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 9 Jun 2011 16:51:47 -0700 Subject: [PATCH 148/186] The map breakage is actually at 2048! --- OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 30cf1dba39..69d300553c 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -209,16 +209,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap // path, param, agentID.ToString()); // There is a major hack going on in this method. The viewer doesn't request - // map blocks (RequestMapBlocks) above 4096. That means that if we don't hack, + // map blocks (RequestMapBlocks) above 2048. That means that if we don't hack, // grids above that cell don't have a map at all. So, here's the hack: we wait // for this CAP request to come, and we inject the map blocks at this point. // In a normal scenario, this request simply sends back the MapLayer (the blue color). // In the hacked scenario, it also sends the map blocks via UDP. // - // 6/8/2011 -- I'm adding an explicit 4096 check, so that we never forget that there is + // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. - if (m_scene.RegionInfo.RegionLocX >= 4096 || m_scene.RegionInfo.RegionLocY >= 4096) + if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) { ScenePresence avatarPresence = null; From 2bc8dcfdbd987ca4a47270c62b77a7eb9ac0f851 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 10 Jun 2011 02:27:45 +0100 Subject: [PATCH 149/186] minor: add method doc to make it clear that click action is fired when the click action is changed, not when a prim is clicked --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index cdb4e412c6..a078291cde 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1504,7 +1504,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// + /// Handle a prim description set request from a viewer. /// /// /// @@ -1521,8 +1521,17 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// Set a click action for the prim. + /// + /// + /// + /// protected internal void PrimClickAction(IClientAPI remoteClient, uint primLocalID, string clickAction) { +// m_log.DebugFormat( +// "[SCENEGRAPH]: User {0} set click action for {1} to {2}", remoteClient.Name, primLocalID, clickAction); + SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) { From 9149ef6c89a5dd5de144022530e5a4facdc91919 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 10 Jun 2011 02:33:50 +0100 Subject: [PATCH 150/186] For MySQL, migrate region tables to the MyISAM storage engine rather than InnoDB Using MyISAM proves vastly faster for persisting scene objects. For instance, a scene object that took 9 seconds to persist before now takes 1. This also improves the experience of loading large OARs. We don't use any of the transactional features of InnoDB. The only thing that may have an impact is that InnoDB does row locking on inserts while MyISAM does table locking. However, field reports say there is no noticeable difference. --- .../Data/MySQL/Resources/RegionStore.migrations | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations index ba8d5388a6..987625bbf0 100644 --- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations @@ -826,3 +826,19 @@ ALTER TABLE `prims` MODIFY COLUMN `CreatorID` VARCHAR(255) NOT NULL DEFAULT ''; ALTER TABLE `primitems` MODIFY COLUMN `CreatorID` VARCHAR(255) NOT NULL DEFAULT ''; COMMIT; + +:VERSION 38 #--------------------- + +BEGIN; + +alter table land ENGINE = MyISAM; +alter table landaccesslist ENGINE = MyISAM; +alter table migrations ENGINE = MyISAM; +alter table primitems ENGINE = MyISAM; +alter table prims ENGINE = MyISAM; +alter table primshapes ENGINE = MyISAM; +alter table regionban ENGINE = MyISAM; +alter table regionsettings ENGINE = MyISAM; +alter table terrain ENGINE = MyISAM; + +COMMIT; \ No newline at end of file From 387b228d68b579bf978c091d8873608e016d0c3d Mon Sep 17 00:00:00 2001 From: dahlia Date: Fri, 10 Jun 2011 00:38:38 -0700 Subject: [PATCH 151/186] partial update for new mesh asset format - handle both old and new formats for physics mesh --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index f89b824614..99b2d8477a 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -303,7 +303,11 @@ namespace OpenSim.Region.Physics.Meshing if (meshOsd is OSDMap) { OSDMap map = (OSDMap)meshOsd; - OSDMap physicsParms = (OSDMap)map["physics_shape"]; + OSDMap physicsParms = (OSDMap)map["physics_shape"]; // old asset format + + if (physicsParms.Count == 0) + physicsParms = (OSDMap)map["physics_mesh"]; // new asset format + int physOffset = physicsParms["offset"].AsInteger() + (int)start; int physSize = physicsParms["size"].AsInteger(); From 98d1e7768af945d3516243f3e010cc4e1fc0788a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 10 Jun 2011 09:16:43 -0700 Subject: [PATCH 152/186] New method for resetting the map on HG: do it only once upon changing grids, and reset only exactly the map blocks that had regions in them. WARNING: this fetches all the regions from the Grid service, so there is a chance that this is a really bad idea in large grids. Pushing it for testing. --- .../EntityTransfer/HGEntityTransferModule.cs | 26 ++++++++ .../CoreModules/Hypergrid/HGWorldMapModule.cs | 66 +++++++++---------- 2 files changed, 59 insertions(+), 33 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 37d81a311f..8df89adfdb 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -147,8 +147,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { base.AgentHasMovedAway(sp, logout); if (logout) + { + // Reset the map + ResetMap(sp); + // Log them out of this grid m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); + } } protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) @@ -280,6 +285,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } + protected void ResetMap(ScenePresence sp) + { + List regions = m_Scenes[0].GridService.GetRegionRange(m_Scenes[0].RegionInfo.ScopeID, 0, 17000 * (int)Constants.RegionSize, 0, 17000 * (int)Constants.RegionSize); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Resetting {0} tiles on the map", regions.Count); + if (regions != null) + { + List mapBlocks = new List(); + foreach (GridRegion r in regions) + { + MapBlockData mblock = new MapBlockData(); + mblock.X = (ushort)(r.RegionLocX / Constants.RegionSize); + mblock.Y = (ushort)(r.RegionLocY / Constants.RegionSize); + mblock.Name = ""; + mblock.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's + mblock.MapImageId = UUID.Zero; + mapBlocks.Add(mblock); + } + sp.ControllingClient.SendMapBlock(mapBlocks, 0); + } + + } #endregion diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs index f066f83540..fd2cc20a1a 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs @@ -59,44 +59,44 @@ namespace OpenSim.Region.CoreModules.Hypergrid #endregion - protected override void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) - { - List mapBlocks = new List(); - List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - minX * (int)Constants.RegionSize, maxX * (int)Constants.RegionSize, - minY * (int)Constants.RegionSize, maxY * (int)Constants.RegionSize); + //protected override void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + //{ + // List mapBlocks = new List(); + // List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, + // minX * (int)Constants.RegionSize, maxX * (int)Constants.RegionSize, + // minY * (int)Constants.RegionSize, maxY * (int)Constants.RegionSize); - foreach (GridRegion r in regions) - { - uint x = 0, y = 0; - long handle = 0; - if (r.RegionSecret != null && r.RegionSecret != string.Empty) - { - if (long.TryParse(r.RegionSecret, out handle)) - { - Utils.LongToUInts((ulong)handle, out x, out y); - x = x / Constants.RegionSize; - y = y / Constants.RegionSize; - } - } + // foreach (GridRegion r in regions) + // { + // uint x = 0, y = 0; + // long handle = 0; + // if (r.RegionSecret != null && r.RegionSecret != string.Empty) + // { + // if (long.TryParse(r.RegionSecret, out handle)) + // { + // Utils.LongToUInts((ulong)handle, out x, out y); + // x = x / Constants.RegionSize; + // y = y / Constants.RegionSize; + // } + // } - if (handle == 0 || - // Check the distance from the current region - (handle != 0 && Math.Abs((int)(x - m_scene.RegionInfo.RegionLocX)) < 4096 && Math.Abs((int)(y - m_scene.RegionInfo.RegionLocY)) < 4096)) - { - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r); - mapBlocks.Add(block); - } - } + // if (handle == 0 || + // // Check the distance from the current region + // (handle != 0 && Math.Abs((int)(x - m_scene.RegionInfo.RegionLocX)) < 4096 && Math.Abs((int)(y - m_scene.RegionInfo.RegionLocY)) < 4096)) + // { + // MapBlockData block = new MapBlockData(); + // MapBlockFromGridRegion(block, r); + // mapBlocks.Add(block); + // } + // } - // Different from super - FillInMap(mapBlocks, minX, minY, maxX, maxY); - // + // // Different from super + // //FillInMap(mapBlocks, minX, minY, maxX, maxY); + // // - remoteClient.SendMapBlock(mapBlocks, 0); + // remoteClient.SendMapBlock(mapBlocks, 0); - } + //} private void FillInMap(List mapBlocks, int minX, int minY, int maxX, int maxY) From b5518dc90631014a4aa3dbb6c27fd5d4c9f612c9 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 10 Jun 2011 20:40:14 +0100 Subject: [PATCH 153/186] minor: Add some commented out destructor logging messages for potential future use. At the moment, client and scene objects are being garbage collected as expected, at least in simple scenarios. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 5 +++++ OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 5 +++++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 7 +++++++ 3 files changed, 17 insertions(+) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index cefceb0beb..f53e2367ce 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -428,6 +428,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Properties +// ~LLClientView() +// { +// m_log.DebugFormat("[LLCLIENTVIEW]: Destructor called for {0}, circuit code {1}", Name, CircuitCode); +// } + /// /// Constructor /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 9b9374b329..79660a3d11 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -469,6 +469,11 @@ namespace OpenSim.Region.Framework.Scenes #endregion +// ~SceneObjectGroup() +// { +// m_log.DebugFormat("[SCENE OBJECT GROUP]: Destructor called for {0}, local id {1}", Name, LocalId); +// } + #region Constructors /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 331abb27b4..a215b20234 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -346,6 +346,13 @@ namespace OpenSim.Region.Framework.Scenes #endregion Fields +// ~SceneObjectPart() +// { +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Destructor called for {0}, local id {1}, parent {2} {3}", +// Name, LocalId, ParentGroup.Name, ParentGroup.LocalId); +// } + #region Constructors /// From 804fe2d9b00e7e974600f17d64375fab8676ad11 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Fri, 20 May 2011 12:52:09 +0300 Subject: [PATCH 154/186] Save the sun's position in OARs --- .../Serialization/External/RegionSettingsSerializer.cs | 8 ++++++-- .../CoreModules/World/Archiver/ArchiveReadRequest.cs | 3 +++ .../CoreModules/World/Archiver/Tests/ArchiverTests.cs | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs index 6ba4c5a55e..931898ce10 100644 --- a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs +++ b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs @@ -182,6 +182,9 @@ namespace OpenSim.Framework.Serialization.External case "FixedSun": settings.FixedSun = bool.Parse(xtr.ReadElementContentAsString()); break; + case "SunPosition": + settings.SunPosition = double.Parse(xtr.ReadElementContentAsString()); + break; } } @@ -237,8 +240,9 @@ namespace OpenSim.Framework.Serialization.External xtw.WriteElementString("TerrainLowerLimit", settings.TerrainLowerLimit.ToString()); xtw.WriteElementString("UseEstateSun", settings.UseEstateSun.ToString()); xtw.WriteElementString("FixedSun", settings.FixedSun.ToString()); - // XXX: Need to expose interface to get sun phase information from sun module - // xtw.WriteStartElement("SunPhase", + xtw.WriteElementString("SunPosition", settings.SunPosition.ToString()); + // Note: 'SunVector' isn't saved because this value is owned by the Sun Module, which + // calculates it automatically according to the date and other factors. xtw.WriteEndElement(); xtw.WriteEndElement(); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 64616365f4..48130e7991 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -488,6 +488,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver currentRegionSettings.Elevation2SE = loadedRegionSettings.Elevation2SE; currentRegionSettings.Elevation2SW = loadedRegionSettings.Elevation2SW; currentRegionSettings.FixedSun = loadedRegionSettings.FixedSun; + currentRegionSettings.SunPosition = loadedRegionSettings.SunPosition; currentRegionSettings.ObjectBonus = loadedRegionSettings.ObjectBonus; currentRegionSettings.RestrictPushing = loadedRegionSettings.RestrictPushing; currentRegionSettings.TerrainLowerLimit = loadedRegionSettings.TerrainLowerLimit; @@ -500,6 +501,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight; currentRegionSettings.Save(); + + m_scene.TriggerEstateSunUpdate(); IEstateModule estateModule = m_scene.RequestModuleInterface(); diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 34e2e23a01..6ba3459747 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -440,6 +440,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests rs.Elevation2SE = 9.2; rs.Elevation2SW = 2.1; rs.FixedSun = true; + rs.SunPosition = 12.0; rs.ObjectBonus = 1.4; rs.RestrictPushing = true; rs.TerrainLowerLimit = 0.4; @@ -485,6 +486,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(loadedRs.Elevation2SE, Is.EqualTo(9.2)); Assert.That(loadedRs.Elevation2SW, Is.EqualTo(2.1)); Assert.That(loadedRs.FixedSun, Is.True); + Assert.AreEqual(12.0, loadedRs.SunPosition); Assert.That(loadedRs.ObjectBonus, Is.EqualTo(1.4)); Assert.That(loadedRs.RestrictPushing, Is.True); Assert.That(loadedRs.TerrainLowerLimit, Is.EqualTo(0.4)); From c7bdb66a1f02c968f61f82333751e7f144fb59d8 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Thu, 9 Jun 2011 22:26:03 +0900 Subject: [PATCH 155/186] Added missing "Old Guids=true" to ConnectionString --- OpenSim/Tests/Clients/Presence/OpenSim.Server.ini | 2 +- OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini | 2 +- bin/config-include/GridCommon.ini.example | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini b/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini index 47e73f9887..8610c78a63 100644 --- a/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini +++ b/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini @@ -29,5 +29,5 @@ port = 8003 [PresenceService] LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService" StorageProvider = "OpenSim.Data.MySQL.dll" - ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;" + ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;Old Guids=true;" diff --git a/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini b/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini index eb1f47346a..453e17e65c 100644 --- a/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini +++ b/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini @@ -29,5 +29,5 @@ port = 8003 [UserAccountService] LocalServiceModule = "OpenSim.Services.UserAccountService.dll:UserAccountService" StorageProvider = "OpenSim.Data.MySQL.dll" - ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;" + ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;Old Guids=true;" diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index e2e6459c58..27f262f374 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -10,9 +10,9 @@ ; Uncomment these lines if you want to use mysql storage ; Change the connection string to your db details ;StorageProvider = "OpenSim.Data.MySQL.dll" - ;ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;" + ;ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;Old Guids=true;" ; Uncomment this line if you are using MySQL and want to use a different database for estates - ;EstateConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;" + ;EstateConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;Old Guids=true;" ; MSSQL ; Uncomment these lines if you want to use MSSQL storage From fc7e17baf74a4b3ce4c47480f24266180dd4353d Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 10 Jun 2011 21:49:25 +0100 Subject: [PATCH 156/186] When serializing objects, stop accidentally using the green text colour value for alpha This addresses http://opensimulator.org/mantis/view.php?id=5111 --- .../Framework/Scenes/Serialization/SceneObjectSerializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 6ae4f3856d..fcf7e0cfec 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -1171,7 +1171,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("R", sop.Color.R.ToString(Utils.EnUsCulture)); writer.WriteElementString("G", sop.Color.G.ToString(Utils.EnUsCulture)); writer.WriteElementString("B", sop.Color.B.ToString(Utils.EnUsCulture)); - writer.WriteElementString("A", sop.Color.G.ToString(Utils.EnUsCulture)); + writer.WriteElementString("A", sop.Color.A.ToString(Utils.EnUsCulture)); writer.WriteEndElement(); writer.WriteElementString("Text", sop.Text); From b13b54c5268d8acada132b678946ceba925f6419 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 11 Jun 2011 00:04:21 +0100 Subject: [PATCH 157/186] Make the internal flotsam asset cache defaults match config-include/FlotsamCache.ini.example. Enable the flotsam console commands even if FlotsamCache.ini isn't present. For the most part, defaults are made to match those already in FlotsamCache.ini.example. The one exception is that the 48 hour file timeout from the code is used instead of the 0 hours that was in the example file. This can be tweaked if necessary. Most importantly, the default cache directory is now ./assetcache (as in FlotsamCache.ini.example) rather than ./FlotsamAssetCache (as was the internal code default). Therefore, if you were using flotasm without using the config file, then please rename your cache directory or start using the ini file and change the default there if you want to keep using your existing cache. --- .../CoreModules/Asset/FlotsamAssetCache.cs | 70 ++++++++++--------- bin/config-include/FlotsamCache.ini.example | 2 +- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 9adb68bc0d..d9280c66e0 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -64,13 +64,13 @@ namespace Flotsam.RegionModules.AssetCache private bool m_Enabled; private const string m_ModuleName = "FlotsamAssetCache"; - private const string m_DefaultCacheDirectory = m_ModuleName; + private const string m_DefaultCacheDirectory = "./assetcache"; private string m_CacheDirectory = m_DefaultCacheDirectory; private readonly List m_InvalidChars = new List(); private int m_LogLevel = 0; - private ulong m_HitRateDisplay = 1; // How often to display hit statistics, given in requests + private ulong m_HitRateDisplay = 100; // How often to display hit statistics, given in requests private static ulong m_Requests; private static ulong m_RequestsForInprogress; @@ -87,14 +87,14 @@ namespace Flotsam.RegionModules.AssetCache #endif private ExpiringCache m_MemoryCache; - private bool m_MemoryCacheEnabled = true; + private bool m_MemoryCacheEnabled = false; // Expiration is expressed in hours. - private const double m_DefaultMemoryExpiration = 1.0; + private const double m_DefaultMemoryExpiration = 2; private const double m_DefaultFileExpiration = 48; private TimeSpan m_MemoryExpiration = TimeSpan.FromHours(m_DefaultMemoryExpiration); private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration); - private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(m_DefaultFileExpiration); + private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(0.166); private static int m_CacheDirectoryTiers = 1; private static int m_CacheDirectoryTierLen = 3; @@ -141,26 +141,38 @@ namespace Flotsam.RegionModules.AssetCache IConfig assetConfig = source.Configs["AssetCache"]; if (assetConfig == null) { - m_log.Warn("[FLOTSAM ASSET CACHE]: AssetCache missing from OpenSim.ini, using defaults."); - m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); - return; + m_log.Warn( + "[FLOTSAM ASSET CACHE]: AssetCache section missing from config (not copied config-include/FlotsamCache.ini.example? Using defaults."); + } + else + { + m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); + + m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled); + m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); + + #if WAIT_ON_INPROGRESS_REQUESTS + m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000); + #endif + + m_LogLevel = assetConfig.GetInt("LogLevel", m_LogLevel); + m_HitRateDisplay = (ulong)assetConfig.GetLong("HitRateDisplay", (long)m_HitRateDisplay); + + m_FileExpiration = TimeSpan.FromHours(assetConfig.GetDouble("FileCacheTimeout", m_DefaultFileExpiration)); + m_FileExpirationCleanupTimer + = TimeSpan.FromHours( + assetConfig.GetDouble("FileCleanupTimer", m_FileExpirationCleanupTimer.TotalHours)); + + m_CacheDirectoryTiers = assetConfig.GetInt("CacheDirectoryTiers", m_CacheDirectoryTiers); + m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); + + m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); + + m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge); } - m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); - m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_CacheDirectory); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); - m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", false); - m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); - -#if WAIT_ON_INPROGRESS_REQUESTS - m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000); -#endif - - m_LogLevel = assetConfig.GetInt("LogLevel", 0); - m_HitRateDisplay = (ulong)assetConfig.GetInt("HitRateDisplay", 1000); - - m_FileExpiration = TimeSpan.FromHours(assetConfig.GetDouble("FileCacheTimeout", m_DefaultFileExpiration)); - m_FileExpirationCleanupTimer = TimeSpan.FromHours(assetConfig.GetDouble("FileCleanupTimer", m_DefaultFileExpiration)); if ((m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero)) { m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds); @@ -170,7 +182,6 @@ namespace Flotsam.RegionModules.AssetCache m_CacheCleanTimer.Start(); } - m_CacheDirectoryTiers = assetConfig.GetInt("CacheDirectoryTiers", 1); if (m_CacheDirectoryTiers < 1) { m_CacheDirectoryTiers = 1; @@ -180,7 +191,6 @@ namespace Flotsam.RegionModules.AssetCache m_CacheDirectoryTiers = 3; } - m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", 3); if (m_CacheDirectoryTierLen < 1) { m_CacheDirectoryTierLen = 1; @@ -190,14 +200,10 @@ namespace Flotsam.RegionModules.AssetCache m_CacheDirectoryTierLen = 4; } - m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", 30000); - - m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", false); - - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand); - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the file and/or memory cache", HandleConsoleCommand); - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand); - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache expire", "fcache expire ", "Purge cached assets older then the specified date/time", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the file and/or memory cache", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache expire", "fcache expire ", "Purge cached assets older then the specified date/time", HandleConsoleCommand); } } } diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example index 026dee718d..1f2bf03162 100644 --- a/bin/config-include/FlotsamCache.ini.example +++ b/bin/config-include/FlotsamCache.ini.example @@ -29,7 +29,7 @@ ; How long {in hours} to keep assets cached on disk, .5 == 30 minutes ; Specify 0 if you do not want your disk cache to expire - FileCacheTimeout = 0 + FileCacheTimeout = 48 ; How often {in hours} should the disk be checked for expired filed ; Specify 0 to disable expiration checking From c7cef650db6bbbabfefa7a2fb47a028147b7e822 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 11 Jun 2011 00:10:40 +0100 Subject: [PATCH 158/186] Make it clear that WaitOnInprogressTimeout is currently a dead setting in FlotsamCache.ini.example --- bin/config-include/FlotsamCache.ini.example | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example index 1f2bf03162..ad38ad15b5 100644 --- a/bin/config-include/FlotsamCache.ini.example +++ b/bin/config-include/FlotsamCache.ini.example @@ -38,6 +38,7 @@ ; If WAIT_ON_INPROGRESS_REQUESTS has been defined then this specifies how ; long (in miliseconds) to block a request thread while trying to complete ; an existing write to disk. + ; NOTE: THIS PARAMETER IS NOT CURRENTLY USED BY THE CACHE ; WaitOnInprogressTimeout = 3000 ; Number of tiers to use for cache directories (current valid From 39e878eb8f23cdae67b917d16f3dfc8709abcd9c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 11 Jun 2011 00:35:31 +0100 Subject: [PATCH 159/186] Align CenomeCache.ini.example values with CenomeCache defaults. --- bin/config-include/CenomeCache.ini.example | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/bin/config-include/CenomeCache.ini.example b/bin/config-include/CenomeCache.ini.example index 8ef4e03bdc..4340493355 100644 --- a/bin/config-include/CenomeCache.ini.example +++ b/bin/config-include/CenomeCache.ini.example @@ -1,13 +1,14 @@ [AssetCache] ;; - ;; Options for CenmoeAssetCache + ;; Options for CenomeAssetCache ;; - ; 256 MB (default: 134217728) - MaxSize = 268435456 + ; Max size of the cache in bytes + ; 134217728 = 128 MB, 26843556 = 256 MB, etc (default: 134217728) + MaxSize = 134217728 - ; How many assets it is possible to store cache (default: 4096) - MaxCount = 16384 + ; How many assets it is possible to store in the cache (default: 4096) + MaxCount = 4096 - ; Expiration time - 1 hour (default: 30 minutes) - ExpirationTime = 60 + ; Expiration time in minutes (default: 30) + ExpirationTime = 30 From 9a62bfab0ea6c60ad2ce8b853b3dae95ef57ac69 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 11 Jun 2011 00:50:20 +0100 Subject: [PATCH 160/186] If the flotsam asset cache console command "fcache clear" is specified on its own, clear both memory and file caches --- .../CoreModules/Asset/FlotsamAssetCache.cs | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index d9280c66e0..48ee277ae9 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -201,7 +201,7 @@ namespace Flotsam.RegionModules.AssetCache } MainConsole.Instance.Commands.AddCommand(Name, true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand); - MainConsole.Instance.Commands.AddCommand(Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the file and/or memory cache", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the cache. If file or memory is specified then only this cache is cleared.", HandleConsoleCommand); MainConsole.Instance.Commands.AddCommand(Name, true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand); MainConsole.Instance.Commands.AddCommand(Name, true, "fcache expire", "fcache expire ", "Purge cached assets older then the specified date/time", HandleConsoleCommand); } @@ -729,24 +729,39 @@ namespace Flotsam.RegionModules.AssetCache break; case "clear": - if (cmdparams.Length < 3) + if (cmdparams.Length < 2) { - m_log.Warn("[FLOTSAM ASSET CACHE] Please specify memory and/or file cache."); + m_log.Warn("[FLOTSAM ASSET CACHE] Usage is fcache clear [file] [memory]"); break; } + + bool clearMemory = false, clearFile = false; + + if (cmdparams.Length == 2) + { + clearMemory = true; + clearFile = true; + } foreach (string s in cmdparams) { if (s.ToLower() == "memory") - { - m_MemoryCache.Clear(); - m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared."); - } + clearMemory = true; else if (s.ToLower() == "file") - { - ClearFileCache(); - m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared."); - } + clearFile = true; } + + if (clearMemory) + { + m_MemoryCache.Clear(); + m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared."); + } + + if (clearFile) + { + ClearFileCache(); + m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared."); + } + break; From 487cb51f69ac2f713797de03eb26a4b53afcfade Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 10 Jun 2011 17:22:17 -0700 Subject: [PATCH 161/186] 3rd way of reseting the HG Map. This time, don't use the grid service; instead keep track of which map blocks each client has seen in the region, and reset exactly those when the client closes. --- .../EntityTransfer/HGEntityTransferModule.cs | 25 ---- .../CoreModules/Hypergrid/HGWorldMapModule.cs | 121 ++++++++++-------- .../World/WorldMap/WorldMapModule.cs | 4 +- 3 files changed, 71 insertions(+), 79 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 8df89adfdb..4d77ef478d 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -148,9 +148,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer base.AgentHasMovedAway(sp, logout); if (logout) { - // Reset the map - ResetMap(sp); - // Log them out of this grid m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); } @@ -285,28 +282,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } - protected void ResetMap(ScenePresence sp) - { - List regions = m_Scenes[0].GridService.GetRegionRange(m_Scenes[0].RegionInfo.ScopeID, 0, 17000 * (int)Constants.RegionSize, 0, 17000 * (int)Constants.RegionSize); - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Resetting {0} tiles on the map", regions.Count); - if (regions != null) - { - List mapBlocks = new List(); - foreach (GridRegion r in regions) - { - MapBlockData mblock = new MapBlockData(); - mblock.X = (ushort)(r.RegionLocX / Constants.RegionSize); - mblock.Y = (ushort)(r.RegionLocY / Constants.RegionSize); - mblock.Name = ""; - mblock.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's - mblock.MapImageId = UUID.Zero; - mapBlocks.Add(mblock); - } - sp.ControllingClient.SendMapBlock(mapBlocks, 0); - } - - } - #endregion #region IUserAgentVerificationModule diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs index fd2cc20a1a..0c60391fe2 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs @@ -41,7 +41,10 @@ namespace OpenSim.Region.CoreModules.Hypergrid { public class HGWorldMapModule : WorldMapModule { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + // Remember the map area that each client has been exposed to in this region + private Dictionary> m_SeenMapBlocks = new Dictionary>(); #region INonSharedRegionModule Members @@ -52,6 +55,13 @@ namespace OpenSim.Region.CoreModules.Hypergrid m_Enabled = true; } + public override void AddRegion(Scene scene) + { + base.AddRegion(scene); + + scene.EventManager.OnClientClosed += new EventManager.ClientClosed(EventManager_OnClientClosed); + } + public override string Name { get { return "HGWorldMap"; } @@ -59,65 +69,70 @@ namespace OpenSim.Region.CoreModules.Hypergrid #endregion - //protected override void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) - //{ - // List mapBlocks = new List(); - // List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - // minX * (int)Constants.RegionSize, maxX * (int)Constants.RegionSize, - // minY * (int)Constants.RegionSize, maxY * (int)Constants.RegionSize); - - // foreach (GridRegion r in regions) - // { - // uint x = 0, y = 0; - // long handle = 0; - // if (r.RegionSecret != null && r.RegionSecret != string.Empty) - // { - // if (long.TryParse(r.RegionSecret, out handle)) - // { - // Utils.LongToUInts((ulong)handle, out x, out y); - // x = x / Constants.RegionSize; - // y = y / Constants.RegionSize; - // } - // } - - // if (handle == 0 || - // // Check the distance from the current region - // (handle != 0 && Math.Abs((int)(x - m_scene.RegionInfo.RegionLocX)) < 4096 && Math.Abs((int)(y - m_scene.RegionInfo.RegionLocY)) < 4096)) - // { - // MapBlockData block = new MapBlockData(); - // MapBlockFromGridRegion(block, r); - // mapBlocks.Add(block); - // } - // } - - // // Different from super - // //FillInMap(mapBlocks, minX, minY, maxX, maxY); - // // - - // remoteClient.SendMapBlock(mapBlocks, 0); - - //} - - - private void FillInMap(List mapBlocks, int minX, int minY, int maxX, int maxY) + void EventManager_OnClientClosed(UUID clientID, Scene scene) { - for (int x = minX; x <= maxX; x++) + ScenePresence sp = scene.GetScenePresence(clientID); + if (sp != null) { - for (int y = minY; y <= maxY; y++) + if (m_SeenMapBlocks.ContainsKey(clientID)) { - MapBlockData mblock = mapBlocks.Find(delegate(MapBlockData mb) { return ((mb.X == x) && (mb.Y == y)); }); - if (mblock == null) + List mapBlocks = m_SeenMapBlocks[clientID]; + foreach (MapBlockData b in mapBlocks) { - mblock = new MapBlockData(); - mblock.X = (ushort)x; - mblock.Y = (ushort)y; - mblock.Name = ""; - mblock.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's - mblock.MapImageId = UUID.Zero; - mapBlocks.Add(mblock); + b.Name = string.Empty; + b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's } + + m_log.DebugFormat("[HG MAP]: Reseting {0} blocks", mapBlocks.Count); + sp.ControllingClient.SendMapBlock(mapBlocks, 0); + m_SeenMapBlocks.Remove(clientID); } } } + + protected override List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + { + List mapBlocks = base.GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); + lock (m_SeenMapBlocks) + { + if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId)) + { + m_SeenMapBlocks.Add(remoteClient.AgentId, mapBlocks); + } + else + { + List seen = m_SeenMapBlocks[remoteClient.AgentId]; + List newBlocks = new List(); + foreach (MapBlockData b in mapBlocks) + if (seen.Find(delegate(MapBlockData bdata) { return bdata.X == b.X && bdata.Y == b.Y; }) == null) + newBlocks.Add(b); + seen.AddRange(newBlocks); + } + } + + return mapBlocks; + } + + } + + class MapArea + { + public int minX; + public int minY; + public int maxX; + public int maxY; + + public MapArea(int mix, int miy, int max, int may) + { + minX = mix; + minY = miy; + maxX = max; + maxY = may; + } + + public void Print() + { + Console.WriteLine(String.Format(" --> Area is minX={0} minY={1} minY={2} maxY={3}", minX, minY, maxY, maxY)); + } } } diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 69d300553c..3553c9af45 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -845,7 +845,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } } - protected virtual void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + protected virtual List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, @@ -860,6 +860,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap mapBlocks.Add(block); } remoteClient.SendMapBlock(mapBlocks, 0); + + return mapBlocks; } protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r) From 0ae022d68822c05130f76a6e80bccd669a3d76ed Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 10 Jun 2011 20:59:57 -0700 Subject: [PATCH 162/186] Decreased timeout of HG StatusNotification to 4secs. http://opensimulator.org/mantis/view.php?id=5516 --- .../Services/Connectors/Hypergrid/UserAgentServiceConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 853e5243ab..b7e09e83d6 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -427,7 +427,7 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - response = request.Send(m_ServerURL, 10000); + response = request.Send(m_ServerURL, 4000); } catch (Exception e) { From 5f311c91c781d09e266fb76cb7747550fe2afc16 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 10 Jun 2011 21:07:50 -0700 Subject: [PATCH 163/186] More tweaking on the UserAgentServiceConnector: add constructor that does not do DNS lookup, and use that for friends notification. --- .../Avatar/Friends/HGFriendsModule.cs | 2 +- .../Hypergrid/UserAgentServiceConnector.cs | 35 ++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index b9d67193ab..b8342efdde 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -278,7 +278,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends List ids = new List(); foreach (FriendInfo f in kvp.Value) ids.Add(f.Friend); - UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key, false); List friendsOnline = uConn.StatusNotification(ids, userID, online); // need to debug this here if (online) diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index b7e09e83d6..2a5fb40475 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -51,22 +51,31 @@ namespace OpenSim.Services.Connectors.Hypergrid MethodBase.GetCurrentMethod().DeclaringType); string m_ServerURL; - public UserAgentServiceConnector(string url) + + public UserAgentServiceConnector(string url) : this(url, true) + { + } + + public UserAgentServiceConnector(string url, bool dnsLookup) { m_ServerURL = url; - // Doing this here, because XML-RPC or mono have some strong ideas about - // caching DNS translations. - try + + if (dnsLookup) { - Uri m_Uri = new Uri(m_ServerURL); - IPAddress ip = Util.GetHostFromDNS(m_Uri.Host); - m_ServerURL = m_ServerURL.Replace(m_Uri.Host, ip.ToString()); - if (!m_ServerURL.EndsWith("/")) - m_ServerURL += "/"; - } - catch (Exception e) - { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Malformed Uri {0}: {1}", m_ServerURL, e.Message); + // Doing this here, because XML-RPC or mono have some strong ideas about + // caching DNS translations. + try + { + Uri m_Uri = new Uri(m_ServerURL); + IPAddress ip = Util.GetHostFromDNS(m_Uri.Host); + m_ServerURL = m_ServerURL.Replace(m_Uri.Host, ip.ToString()); + if (!m_ServerURL.EndsWith("/")) + m_ServerURL += "/"; + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Malformed Uri {0}: {1}", m_ServerURL, e.Message); + } } m_log.DebugFormat("[USER AGENT CONNECTOR]: new connector to {0} ({1})", url, m_ServerURL); } From e07d71d2982ac2c128035fee29991eda949bd8dd Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 10 Jun 2011 21:17:34 -0700 Subject: [PATCH 164/186] Added a Sleep in between each site call, to slow the xml-rpc requests down. --- .../Avatar/Friends/HGFriendsModule.cs | 77 ++++++++++--------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index b8342efdde..40506a5aeb 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -29,6 +29,8 @@ using System; using System.Collections; using System.Collections.Generic; using System.Reflection; +using System.Threading; + using log4net; using Nini.Config; using Nwc.XmlRpc; @@ -194,46 +196,46 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends //} - private void CollectOnlineFriendsElsewhere(UUID userID, List foreignFriends) - { - // let's divide the friends on a per-domain basis - Dictionary> friendsPerDomain = new Dictionary>(); - foreach (string friend in foreignFriends) - { - UUID friendID; - if (!UUID.TryParse(friend, out friendID)) - { - // it's a foreign friend - string url = string.Empty, tmp = string.Empty; - if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp)) - { - if (!friendsPerDomain.ContainsKey(url)) - friendsPerDomain[url] = new List(); - friendsPerDomain[url].Add(friend); - } - } - } + //private void CollectOnlineFriendsElsewhere(UUID userID, List foreignFriends) + //{ + // // let's divide the friends on a per-domain basis + // Dictionary> friendsPerDomain = new Dictionary>(); + // foreach (string friend in foreignFriends) + // { + // UUID friendID; + // if (!UUID.TryParse(friend, out friendID)) + // { + // // it's a foreign friend + // string url = string.Empty, tmp = string.Empty; + // if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp)) + // { + // if (!friendsPerDomain.ContainsKey(url)) + // friendsPerDomain[url] = new List(); + // friendsPerDomain[url].Add(friend); + // } + // } + // } - // Now, call those worlds + // // Now, call those worlds - foreach (KeyValuePair> kvp in friendsPerDomain) - { - List ids = new List(); - foreach (string f in kvp.Value) - ids.Add(f); - UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); - List online = uConn.GetOnlineFriends(userID, ids); - // Finally send the notifications to the user - // this whole process may take a while, so let's check at every - // iteration that the user is still here - IClientAPI client = LocateClientObject(userID); - if (client != null) - client.SendAgentOnline(online.ToArray()); - else - break; - } + // foreach (KeyValuePair> kvp in friendsPerDomain) + // { + // List ids = new List(); + // foreach (string f in kvp.Value) + // ids.Add(f); + // UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + // List online = uConn.GetOnlineFriends(userID, ids); + // // Finally send the notifications to the user + // // this whole process may take a while, so let's check at every + // // iteration that the user is still here + // IClientAPI client = LocateClientObject(userID); + // if (client != null) + // client.SendAgentOnline(online.ToArray()); + // else + // break; + // } - } + //} protected override void StatusNotify(List friendList, UUID userID, bool online) { @@ -280,6 +282,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends ids.Add(f.Friend); UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key, false); List friendsOnline = uConn.StatusNotification(ids, userID, online); + Thread.Sleep(100); // need to debug this here if (online) { From d99277939750247ad100395394720c73a3580c72 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 11 Jun 2011 09:36:57 -0700 Subject: [PATCH 165/186] Switched order of SQL statements in Friends migration -- resulted in the wrong key --- OpenSim/Data/MySQL/Resources/FriendsStore.migrations | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations index 7848e49955..55d82eca73 100644 --- a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations +++ b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations @@ -25,8 +25,8 @@ COMMIT; BEGIN; +ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; ALTER TABLE `Friends` DROP PRIMARY KEY; ALTER TABLE `Friends` ADD PRIMARY KEY(PrincipalID(36), Friend(36)); -ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; COMMIT; From e1ca77a0dbc68431131b0505f03cf45dbfe5b7d9 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 11 Jun 2011 17:22:35 -0700 Subject: [PATCH 166/186] Only send AgentOnline to the client if the friendsOnline list has elements. Also, increased the timeout on UserAgentServiceConnector, StatusNotification again. --- OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs | 2 +- .../Services/Connectors/Hypergrid/UserAgentServiceConnector.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index 40506a5aeb..2c915140fe 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -284,7 +284,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends List friendsOnline = uConn.StatusNotification(ids, userID, online); Thread.Sleep(100); // need to debug this here - if (online) + if (online && friendsOnline.Count > 0) { IClientAPI client = LocateClientObject(userID); if (client != null) diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 2a5fb40475..6265bcd3fc 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -436,7 +436,7 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - response = request.Send(m_ServerURL, 4000); + response = request.Send(m_ServerURL, 6000); } catch (Exception e) { From 06e254c392c754bf7e7a1c80400a3ef5b1a82ca3 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 11 Jun 2011 17:48:19 -0700 Subject: [PATCH 167/186] A few more cleanups on the way to close http://opensimulator.org/mantis/view.php?id=5516 once and for all. Moral of the story: don't send AgentOnline/Offline to viewers with a zero-length array. --- .../CoreModules/Avatar/Friends/HGFriendsModule.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index 2c915140fe..dda67f9c2b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -280,10 +280,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends List ids = new List(); foreach (FriendInfo f in kvp.Value) ids.Add(f.Friend); - UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key, false); + UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); List friendsOnline = uConn.StatusNotification(ids, userID, online); - Thread.Sleep(100); - // need to debug this here + if (online && friendsOnline.Count > 0) { IClientAPI client = LocateClientObject(userID); @@ -305,15 +304,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last, out tmp)) { IUserManagement userMan = m_Scenes[0].RequestModuleInterface(); - userMan.AddUser(agentID, url + ";" + first + " " + last); + userMan.AddUser(agentID, first, last, url); - try // our best - { - string[] parts = userMan.GetUserName(agentID).Split(); - first = parts[0]; - last = parts[1]; - } - catch { } return true; } return false; From fd57c91b4a10cf7ee1e94dc8fe4e81eb0d5bae3d Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 15:37:42 -0700 Subject: [PATCH 168/186] First pass at making the V2 map work. Standalones only for now. There are some issues with the zoom level -- TBD. --- .../Servers/HttpServer/BaseHttpServer.cs | 4 +- .../MapImageServiceInConnectorModule.cs | 111 +++++++ .../MapImage/MapImageServiceModule.cs | 232 ++++++++++++++ .../World/WorldMap/WorldMapModule.cs | 8 +- .../Handlers/Map/MapAddServerConnector.cs | 61 ++++ .../Handlers/Map/MapGetServerConnector.cs | 105 +++++++ .../MapImage/MapImageServiceConnector.cs | 158 ++++++++++ .../{IMapService.cs => IMapImageService.cs} | 6 +- .../MapImageService/MapImageService.cs | 295 ++++++++++++++++++ bin/config-include/Standalone.ini | 7 + .../StandaloneCommon.ini.example | 3 + bin/config-include/StandaloneHypergrid.ini | 11 +- prebuild.xml | 30 ++ 13 files changed, 1021 insertions(+), 10 deletions(-) create mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs create mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs create mode 100644 OpenSim/Server/Handlers/Map/MapAddServerConnector.cs create mode 100644 OpenSim/Server/Handlers/Map/MapGetServerConnector.cs create mode 100644 OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs rename OpenSim/Services/Interfaces/{IMapService.cs => IMapImageService.cs} (86%) create mode 100644 OpenSim/Services/MapImageService/MapImageService.cs diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 598e5d17cd..cb1117ae55 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -412,7 +412,7 @@ namespace OpenSim.Framework.Servers.HttpServer // OpenSim.Framework.WebUtil.OSHeaderRequestID if (request.Headers["opensim-request-id"] != null) reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]); - // m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); + //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); @@ -440,7 +440,7 @@ namespace OpenSim.Framework.Servers.HttpServer string path = request.RawUrl; string handlerKey = GetHandlerKey(request.HttpMethod, path); -// m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); + //m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); if (TryGetStreamHandler(handlerKey, out requestHandler)) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs new file mode 100644 index 0000000000..b570155048 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs @@ -0,0 +1,111 @@ +/* + * 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.Collections.Generic; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Server.Base; +using OpenSim.Server.Handlers.Base; +using OpenSim.Server.Handlers.MapImage; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.MapImage +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class MapImageServiceInConnectorModule : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static bool m_Enabled = false; + + private IConfigSource m_Config; + bool m_Registered = false; + + #region IRegionModule interface + + public void Initialise(IConfigSource config) + { + m_Config = config; + IConfig moduleConfig = config.Configs["Modules"]; + if (moduleConfig != null) + { + m_Enabled = moduleConfig.GetBoolean("MapImageServiceInConnector", false); + if (m_Enabled) + { + m_log.Info("[MAP SERVICE IN CONNECTOR]: MapImage Service In Connector enabled"); + new MapGetServiceConnector(m_Config, MainServer.Instance, "MapImageService"); + } + + } + + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public string Name + { + get { return "MapImageServiceIn"; } + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + } + + #endregion + + } +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs new file mode 100644 index 0000000000..ee90859744 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs @@ -0,0 +1,232 @@ +/* + * 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 System.Net; +using System.IO; +using System.Timers; +using System.Drawing; +using System.Drawing.Imaging; + +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 OpenSim.Server.Base; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage +{ + /// + /// + /// + /// + + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class MapImageServiceModule : ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private bool m_enabled = false; + private IMapImageService m_MapService; + + private string m_serverUrl = String.Empty; + private Dictionary m_scenes = new Dictionary(); + + private int m_refreshtime = 0; + private int m_lastrefresh = 0; + private System.Timers.Timer m_refreshTimer = new System.Timers.Timer(); + + #region ISharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public string Name { get { return "MapImageServiceModule"; } } + public void RegionLoaded(Scene scene) { } + public void Close() { } + public void PostInitialise() { } + + + /// + /// + /// + public void Initialise(IConfigSource source) + { + IConfig moduleConfig = source.Configs["Modules"]; + if (moduleConfig != null) + { + string name = moduleConfig.GetString("MapImageService", ""); + if (name != Name) + return; + } + + IConfig config = source.Configs["MapImageService"]; + if (config == null) + return; + + int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime")); + if (refreshminutes <= 0) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No refresh time given in config. Module disabled."); + return; + } + + m_refreshtime = refreshminutes * 60 * 1000; // convert from minutes to ms + + string service = config.GetString("LocalServiceModule", string.Empty); + if (service == string.Empty) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No service dll given in config. Unable to proceed."); + return; + } + + Object[] args = new Object[] { source }; + m_MapService = ServerUtils.LoadPlugin(service, args); + + m_refreshTimer.Enabled = true; + m_refreshTimer.AutoReset = true; + m_refreshTimer.Interval = m_refreshtime; + m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh); + + m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0}min and service object {1}", + refreshminutes, service); + + m_enabled = true; + } + + /// + /// + /// + + + /// + /// + /// + public void AddRegion(Scene scene) + { + if (! m_enabled) + return; + + // Every shared region module has to maintain an indepedent list of + // currently running regions + lock (m_scenes) + m_scenes[scene.RegionInfo.RegionID] = scene; + + scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); + } + + /// + /// + /// + public void RemoveRegion(Scene scene) + { + if (! m_enabled) + return; + + lock (m_scenes) + m_scenes.Remove(scene.RegionInfo.RegionID); + } + + #endregion ISharedRegionModule + + void EventManager_OnPrimsLoaded(Scene s) + { + UploadMapTile(s); + } + + + /// + /// + /// + private void HandleMaptileRefresh(object sender, EventArgs ea) + { + // this approach is a bit convoluted becase we want to wait for the + // first upload to happen on startup but after all the objects are + // loaded and initialized + if (m_lastrefresh > 0 && Util.EnvironmentTickCountSubtract(m_lastrefresh) < m_refreshtime) + return; + + m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: map refresh!"); + lock (m_scenes) + { + foreach (IScene scene in m_scenes.Values) + { + try + { + UploadMapTile(scene); + } + catch (Exception ex) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: something bad happened {0}", ex.Message); + } + } + } + + m_lastrefresh = Util.EnvironmentTickCount(); + } + + /// + /// + /// + private void UploadMapTile(IScene scene) + { + m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName); + + // Create a PNG map tile and upload it to the AddMapTile API + byte[] jpgData = Utils.EmptyBytes; + IMapImageGenerator tileGenerator = scene.RequestModuleInterface(); + if (tileGenerator == null) + { + m_log.Warn("[MAP IMAGE SERVICE MODULE]: Cannot upload PNG map tile without an ImageGenerator"); + return; + } + + using (Image mapTile = tileGenerator.CreateMapTile()) + { + using (MemoryStream stream = new MemoryStream()) + { + mapTile.Save(stream, ImageFormat.Jpeg); + jpgData = stream.ToArray(); + } + } + + string reason = string.Empty; + if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, out reason)) + { + m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: Unable to upload tile image for {0} at {1}-{2}: {3}", + scene.RegionInfo.RegionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, reason); + } + + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 3553c9af45..079b1c205d 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -849,10 +849,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - (minX - 4) * (int)Constants.RegionSize, - (maxX + 4) * (int)Constants.RegionSize, - (minY - 4) * (int)Constants.RegionSize, - (maxY + 4) * (int)Constants.RegionSize); + (minX - 8) * (int)Constants.RegionSize, + (maxX + 8) * (int)Constants.RegionSize, + (minY - 8) * (int)Constants.RegionSize, + (maxY + 8) * (int)Constants.RegionSize); foreach (GridRegion r in regions) { MapBlockData block = new MapBlockData(); diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs new file mode 100644 index 0000000000..a953cd7eaf --- /dev/null +++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs @@ -0,0 +1,61 @@ +/* + * 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; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.MapImage +{ + public class MapAddServiceConnector : ServiceConnector + { + private IMapImageService m_MapService; + private string m_ConfigName = "MapImageService"; + + public MapAddServiceConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); + + string gridService = serverConfig.GetString("LocalServiceModule", + String.Empty); + + if (gridService == String.Empty) + throw new Exception("No LocalServiceModule in config file"); + + Object[] args = new Object[] { config }; + m_MapService = ServerUtils.LoadPlugin(gridService, args); + + //server.AddStreamHandler(new PresenceServerPostHandler(m_PresenceService)); + } + } +} diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs new file mode 100644 index 0000000000..9448af743b --- /dev/null +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -0,0 +1,105 @@ +/* + * 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.IO; +using System.Net; +using System.Reflection; + +using Nini.Config; +using log4net; + +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.MapImage +{ + public class MapGetServiceConnector : ServiceConnector + { + private IMapImageService m_MapService; + private string m_ConfigName = "MapImageService"; + + public MapGetServiceConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); + + string gridService = serverConfig.GetString("LocalServiceModule", + String.Empty); + + if (gridService == String.Empty) + throw new Exception("No LocalServiceModule in config file"); + + Object[] args = new Object[] { config }; + m_MapService = ServerUtils.LoadPlugin(gridService, args); + + server.AddStreamHandler(new MapServerGetHandler(m_MapService)); + } + } + + class MapServerGetHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IMapImageService m_MapService; + + public MapServerGetHandler(IMapImageService service) : + base("GET", "/map") + { + m_MapService = service; + } + + public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: retrieving {0}", path); + byte[] result = new byte[0]; + + string format = string.Empty; + result = m_MapService.GetMapTile(path.Trim('/'), out format); + + if (result.Length > 0) + { + httpResponse.StatusCode = (int)HttpStatusCode.OK; + if (format.Equals("png")) + httpResponse.ContentType = "image/png"; + else if (format.Equals("jpg") || format.Equals("jpeg")) + httpResponse.ContentType = "image/jpeg"; + } + else + { + httpResponse.StatusCode = (int)HttpStatusCode.NotFound; + httpResponse.ContentType = "text/plain"; + } + + return result; + } + + } +} diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs new file mode 100644 index 0000000000..ff0e9d9aee --- /dev/null +++ b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs @@ -0,0 +1,158 @@ +/* + * 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.Net; +using System.Reflection; + +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Communications; +using OpenSim.Services.Interfaces; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Services.Connectors +{ + public class MapImageServicesConnector : IMapImageService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI = String.Empty; + private IImprovedAssetCache m_Cache = null; + + public MapImageServicesConnector() + { + } + + public MapImageServicesConnector(string serverURI) + { + m_ServerURI = serverURI.TrimEnd('/'); + } + + public MapImageServicesConnector(IConfigSource source) + { + Initialise(source); + } + + public virtual void Initialise(IConfigSource source) + { + IConfig config = source.Configs["MapImageService"]; + if (config == null) + { + m_log.Error("[MAP IMAGE CONNECTOR]: MapImageService missing"); + throw new Exception("MapImage connector init error"); + } + + string serviceURI = config.GetString("MapImageServerURI", + String.Empty); + + if (serviceURI == String.Empty) + { + m_log.Error("[MAP IMAGE CONNECTOR]: No Server URI named in section MapImageService"); + throw new Exception("MapImage connector init error"); + } + m_ServerURI = serviceURI; + } + + public bool AddMapTile(int x, int y, byte[] pngData, out string reason) + { + List postParameters = new List() + { + new MultipartForm.Parameter("X", x.ToString()), + new MultipartForm.Parameter("Y", y.ToString()), + new MultipartForm.File("Tile", "tile.png", "image/png", pngData) + }; + + reason = string.Empty; + int tickstart = Util.EnvironmentTickCount(); + + // Make the remote storage request + try + { + HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI); + request.Timeout = 20000; + request.ReadWriteTimeout = 5000; + + using (HttpWebResponse response = MultipartForm.Post(request, postParameters)) + { + using (Stream responseStream = response.GetResponseStream()) + { + string responseStr = responseStream.GetStreamString(); + OSD responseOSD = OSDParser.Deserialize(responseStr); + if (responseOSD.Type == OSDType.Map) + { + OSDMap responseMap = (OSDMap)responseOSD; + if (responseMap["Success"].AsBoolean()) + return true; + + reason = "Upload failed: " + responseMap["Message"].AsString(); + } + else + { + reason = "Response format was invalid:\n" + responseStr; + } + } + } + } + catch (WebException we) + { + reason = we.Message; + if (we.Status == WebExceptionStatus.ProtocolError) + { + HttpWebResponse webResponse = (HttpWebResponse)we.Response; + reason = String.Format("[{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription); + } + } + catch (Exception ex) + { + reason = ex.Message; + } + 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); + } + + return false; + } + + public byte[] GetMapTile(string fileName, out string format) + { + format = string.Empty; + new Exception("GetMapTile method not Implemented"); + return null; + } + } +} diff --git a/OpenSim/Services/Interfaces/IMapService.cs b/OpenSim/Services/Interfaces/IMapImageService.cs similarity index 86% rename from OpenSim/Services/Interfaces/IMapService.cs rename to OpenSim/Services/Interfaces/IMapImageService.cs index c70f484f08..a7b2cf1dfd 100644 --- a/OpenSim/Services/Interfaces/IMapService.cs +++ b/OpenSim/Services/Interfaces/IMapImageService.cs @@ -31,8 +31,10 @@ using OpenMetaverse; namespace OpenSim.Services.Interfaces { - public interface IMapService + public interface IMapImageService { - List GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY); + //List GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY); + bool AddMapTile(int x, int y, byte[] imageData, out string reason); + byte[] GetMapTile(string fileName, out string format); } } diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs new file mode 100644 index 0000000000..596c4a6f48 --- /dev/null +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -0,0 +1,295 @@ +/* + * 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.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Net; +using System.Reflection; + +using Nini.Config; +using log4net; +using OpenMetaverse; + +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Services.Interfaces; + + +namespace OpenSim.Services.MapImageService +{ + public class MapImageService : IMapImageService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private const int ZOOM_LEVELS = 8; + private const int IMAGE_WIDTH = 256; + private const int HALF_WIDTH = 128; + private const int JPEG_QUALITY = 80; + + private static string m_TilesStoragePath = "maptiles"; + + private static object m_Sync = new object(); + private static bool m_Initialized = false; + private static string m_WaterTileFile = string.Empty; + private static Color m_Watercolor = Color.FromArgb(29, 71, 95); + + public MapImageService(IConfigSource config) + { + if (!m_Initialized) + { + m_Initialized = true; + m_log.Debug("[MAP IMAGE SERVICE]: Starting MapImage service"); + + IConfig serviceConfig = config.Configs["MapImageService"]; + if (serviceConfig != null) + { + m_TilesStoragePath = serviceConfig.GetString("TilesStoragePath", m_TilesStoragePath); + if (!Directory.Exists(m_TilesStoragePath)) + Directory.CreateDirectory(m_TilesStoragePath); + + + m_WaterTileFile = Path.Combine(m_TilesStoragePath, "water.jpg"); + if (!File.Exists(m_WaterTileFile)) + { + Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH); + FillImage(waterTile, m_Watercolor); + waterTile.Save(m_WaterTileFile); + } + } + } + } + + #region IMapImageService + + public bool AddMapTile(int x, int y, byte[] imageData, out string reason) + { + reason = string.Empty; + string fileName = GetFileName(1, x, y); + + lock (m_Sync) + { + try + { + using (FileStream f = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write)) + f.Write(imageData, 0, imageData.Length); + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to save image file {0}: {1}", fileName, e); + reason = e.Message; + return false; + } + + // Also save in png format? + + // Stitch seven more aggregate tiles together + for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++) + { + // 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); + + if (!CreateTile(zoomLevel, x1, y1)) + { + 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; + } + } + } + + return true; + } + + public byte[] GetMapTile(string fileName, out string format) + { + format = "jpg"; + string fullName = Path.Combine(m_TilesStoragePath, fileName); + if (File.Exists(fullName)) + { + format = Path.GetExtension(fileName).ToLower(); + m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format); + return File.ReadAllBytes(fullName); + } + else if (File.Exists(m_WaterTileFile)) + { + m_log.DebugFormat("[MAP IMAGE SERVICE]: File not found {0}, sending water", fileName); + return File.ReadAllBytes(m_WaterTileFile); + } + else + { + m_log.DebugFormat("[MAP IMAGE SERVICE]: unable to get file {0}", fileName); + return new byte[0]; + } + } + + #endregion + + + private string GetFileName(uint zoomLevel, int x, int y) + { + string extension = "jpg"; + return Path.Combine(m_TilesStoragePath, string.Format("map-{0}-{1}-{2}-objects.{3}", zoomLevel, x, y, extension)); + } + + private Bitmap GetInputTileImage(string fileName) + { + try + { + if (File.Exists(fileName)) + return new Bitmap(fileName); + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e); + } + + return null; + } + + private Bitmap GetOutputTileImage(string fileName) + { + try + { + if (File.Exists(fileName)) + return new Bitmap(fileName); + + else + { + // Create a new output tile with a transparent background + Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH); + bm.MakeTransparent(); + return bm; + } + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e); + } + + return null; + } + + private bool CreateTile(uint zoomLevel, int x, int y) + { + m_log.DebugFormat("[MAP IMAGE SERVICE]: Create tile for {0} {1}, zoom {2}", x, y, zoomLevel); + int prevWidth = (int)Math.Pow(2, (double)zoomLevel - 2); + int thisWidth = (int)Math.Pow(2, (double)zoomLevel - 1); + + // Convert x and y to the bottom left tile for this zoom level + int xIn = x - (x % prevWidth); + int yIn = y - (y % prevWidth); + + // Convert x and y to the bottom left tile for the next zoom level + int xOut = x - (x % thisWidth); + int yOut = y - (y % thisWidth); + + // Try to open the four input tiles from the previous zoom level + Bitmap inputBL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn)); + Bitmap inputBR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn)); + Bitmap inputTL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn + prevWidth)); + Bitmap inputTR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn + prevWidth)); + + // Open the output tile (current zoom level) + string outputFile = GetFileName(zoomLevel, xOut, yOut); + Bitmap output = GetOutputTileImage(outputFile); + if (output == null) + return false; + FillImage(output, m_Watercolor); + + if (inputBL != null) + { + ImageCopyResampled(output, inputBL, 0, HALF_WIDTH, 0, 0); + inputBL.Dispose(); + } + if (inputBR != null) + { + ImageCopyResampled(output, inputBR, HALF_WIDTH, HALF_WIDTH, 0, 0); + inputBR.Dispose(); + } + if (inputTL != null) + { + ImageCopyResampled(output, inputTL, 0, 0, 0, 0); + inputTL.Dispose(); + } + if (inputTR != null) + { + ImageCopyResampled(output, inputTR, HALF_WIDTH, 0, 0, 0); + inputTR.Dispose(); + } + + // Write the modified output + try + { + using (Bitmap final = new Bitmap(output)) + { + output.Dispose(); + final.Save(outputFile); + } + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Oops on saving {0} {1}", outputFile, e); + } + + // Save also as png? + + return true; + } + + #region Image utilities + + private void FillImage(Bitmap bm, Color c) + { + for (int x = 0; x < bm.Width; x++) + for (int y = 0; y < bm.Height; y++) + bm.SetPixel(x, y, c); + } + + private void ImageCopyResampled(Bitmap output, Bitmap input, int destX, int destY, int srcX, int srcY) + { + int resamplingRateX = 2; // (input.Width - srcX) / (output.Width - destX); + int resamplingRateY = 2; // (input.Height - srcY) / (output.Height - destY); + + for (int x = destX; x < destX + HALF_WIDTH; x++) + for (int y = destY; y < destY + HALF_WIDTH; y++) + { + Color p = input.GetPixel(srcX + (x - destX) * resamplingRateX, srcY + (y - destY) * resamplingRateY); + output.SetPixel(x, y, p); + } + } + + #endregion + } +} diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini index 4ff1a269bf..bf89d0bb9c 100644 --- a/bin/config-include/Standalone.ini +++ b/bin/config-include/Standalone.ini @@ -17,10 +17,12 @@ AvatarServices = "LocalAvatarServicesConnector" EntityTransferModule = "BasicEntityTransferModule" InventoryAccessModule = "BasicInventoryAccessModule" + MapImageService = "MapImageServiceModule" LibraryModule = true LLLoginServiceInConnector = true GridInfoServiceInConnector = true + MapImageServiceInConnector = true [Profile] Module = "BasicProfileModule" @@ -91,6 +93,11 @@ WelcomeMessage = "Welcome, Avatar!" +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; in minutes + RefreshTime = 60 + ;; This should always be the very last thing on this file [Includes] Include-Common = "config-include/StandaloneCommon.ini" diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 7359bba62f..69349d2b49 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -99,6 +99,9 @@ SRV_FriendsServerURI = "http://127.0.0.1:9000" SRV_IMServerURI = "http://127.0.0.1:9000" + ;; For Viewer 2 + MapTileURL = "http://127.0.0.1:9000" + ;; Regular expressions for controlling which client versions are accepted/denied. ;; An empty string means nothing is checked. ;; diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index 8480a77bbd..719df5c5c3 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -18,9 +18,10 @@ GridUserServices = "LocalGridUserServicesConnector" SimulationServices = "RemoteSimulationConnectorModule" AvatarServices = "LocalAvatarServicesConnector" + MapImageService = "MapImageServiceModule" EntityTransferModule = "HGEntityTransferModule" InventoryAccessModule = "HGInventoryAccessModule" - FriendsModule = "HGFriendsModule" + FriendsModule = "HGFriendsModule" InventoryServiceInConnector = true AssetServiceInConnector = true @@ -31,6 +32,7 @@ GridInfoServiceInConnector = true AuthenticationServiceInConnector = true SimulationServiceInConnector = true + MapImageServiceInConnector = true [Profile] Module = "BasicProfileModule" @@ -116,7 +118,12 @@ GridService = "OpenSim.Services.GridService.dll:GridService" AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService" FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" - + +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; in minutes + RefreshTime = 60 + [GatekeeperService] LocalServiceModule = "OpenSim.Services.HypergridService.dll:GatekeeperService" ;; for the service diff --git a/prebuild.xml b/prebuild.xml index 90f451d6a7..ed79b40c39 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1269,6 +1269,36 @@ + + + + ../../../bin/ + + + + + ../../../bin/ + + + + ../../../bin/ + + + + + + + + + + + + + + + + + From 78c16da5444a2e363de50bc88c8d2b929dec0989 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 17:05:45 -0700 Subject: [PATCH 169/186] A few bug fixes on map V2. Zoom level weirdness still there. --- .../World/WorldMap/WorldMapModule.cs | 18 ++++++++++++------ .../Handlers/Map/MapGetServerConnector.cs | 5 ++--- .../MapImageService/MapImageService.cs | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 079b1c205d..6e142bb2da 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -836,7 +836,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap block.Access = 254; // means 'simulator is offline' response.Add(block); } - remoteClient.SendMapBlock(response, 0); + if ((flag & 2) == 2) // V2 !!! + remoteClient.SendMapBlock(response, 2); + else + remoteClient.SendMapBlock(response, 0); } else { @@ -849,17 +852,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - (minX - 8) * (int)Constants.RegionSize, - (maxX + 8) * (int)Constants.RegionSize, - (minY - 8) * (int)Constants.RegionSize, - (maxY + 8) * (int)Constants.RegionSize); + (minX - 4) * (int)Constants.RegionSize, + (maxX + 4) * (int)Constants.RegionSize, + (minY - 4) * (int)Constants.RegionSize, + (maxY + 4) * (int)Constants.RegionSize); foreach (GridRegion r in regions) { MapBlockData block = new MapBlockData(); MapBlockFromGridRegion(block, r); mapBlocks.Add(block); } - remoteClient.SendMapBlock(mapBlocks, 0); + if ((flag & 2) == 2) // V2 !!! + remoteClient.SendMapBlock(mapBlocks, 2); + else + remoteClient.SendMapBlock(mapBlocks, 0); return mapBlocks; } diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs index 9448af743b..76dd695fe7 100644 --- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -83,13 +83,12 @@ namespace OpenSim.Server.Handlers.MapImage string format = string.Empty; result = m_MapService.GetMapTile(path.Trim('/'), out format); - if (result.Length > 0) { httpResponse.StatusCode = (int)HttpStatusCode.OK; - if (format.Equals("png")) + if (format.Equals(".png")) httpResponse.ContentType = "image/png"; - else if (format.Equals("jpg") || format.Equals("jpeg")) + else if (format.Equals(".jpg") || format.Equals(".jpeg")) httpResponse.ContentType = "image/jpeg"; } else diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs index 596c4a6f48..ee424e14f3 100644 --- a/OpenSim/Services/MapImageService/MapImageService.cs +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -134,7 +134,7 @@ namespace OpenSim.Services.MapImageService public byte[] GetMapTile(string fileName, out string format) { - format = "jpg"; + format = ".jpg"; string fullName = Path.Combine(m_TilesStoragePath, fileName); if (File.Exists(fullName)) { From 07d7c1cd2d0d5ccf6d40a3616ecaeb565e9bfab4 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 18:29:44 -0700 Subject: [PATCH 170/186] Trailing / in MapTileURL must be there! --- bin/config-include/StandaloneCommon.ini.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 69349d2b49..29c2af1f96 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -100,7 +100,7 @@ SRV_IMServerURI = "http://127.0.0.1:9000" ;; For Viewer 2 - MapTileURL = "http://127.0.0.1:9000" + MapTileURL = "http://127.0.0.1:9000/" ;; Regular expressions for controlling which client versions are accepted/denied. ;; An empty string means nothing is checked. From 2e77518c6dd5f06c965df758ebd0a20a39c96dc8 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 21:51:26 -0700 Subject: [PATCH 171/186] bit depth: 24!!! begeez! -- zoom levels work now. --- OpenSim/Server/Handlers/Map/MapGetServerConnector.cs | 4 +++- OpenSim/Services/MapImageService/MapImageService.cs | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs index 76dd695fe7..53d08faa3b 100644 --- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -42,11 +42,13 @@ namespace OpenSim.Server.Handlers.MapImage { public class MapGetServiceConnector : ServiceConnector { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IMapImageService m_MapService; + private string m_ConfigName = "MapImageService"; public MapGetServiceConnector(IConfigSource config, IHttpServer server, string configName) : - base(config, server, configName) + base(config, server, configName) { IConfig serverConfig = config.Configs[m_ConfigName]; if (serverConfig == null) diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs index ee424e14f3..736fa2ebac 100644 --- a/OpenSim/Services/MapImageService/MapImageService.cs +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -144,7 +144,6 @@ namespace OpenSim.Services.MapImageService } else if (File.Exists(m_WaterTileFile)) { - m_log.DebugFormat("[MAP IMAGE SERVICE]: File not found {0}, sending water", fileName); return File.ReadAllBytes(m_WaterTileFile); } else @@ -188,7 +187,7 @@ namespace OpenSim.Services.MapImageService else { // Create a new output tile with a transparent background - Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH); + Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH, PixelFormat.Format24bppRgb); bm.MakeTransparent(); return bm; } @@ -255,7 +254,7 @@ namespace OpenSim.Services.MapImageService using (Bitmap final = new Bitmap(output)) { output.Dispose(); - final.Save(outputFile); + final.Save(outputFile, ImageFormat.Jpeg); } } catch (Exception e) From 95e050130c42c21ca4f26b31abce1c4a83194525 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 22:10:16 -0700 Subject: [PATCH 172/186] People are bound to forget the '/' at the end of MapTileURL, so let's correct that from the inside. --- OpenSim/Services/LLLoginService/LLLoginService.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 5d1779a15c..2b15896d69 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -112,6 +112,14 @@ namespace OpenSim.Services.LLLoginService m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty); m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty); + // Clean up some of these vars + if (m_MapTileURL != String.Empty) + { + m_MapTileURL = m_MapTileURL.Trim(); + if (!m_MapTileURL.EndsWith("/")) + m_MapTileURL = m_MapTileURL + "/"; + } + // These are required; the others aren't if (accountService == string.Empty || authService == string.Empty) throw new Exception("LoginService is missing service specifications"); From 4b9de140ab9aa9312219610de68138c4288b840a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 22:25:30 -0700 Subject: [PATCH 173/186] Add credit and link to SimianGrid project. Thanks, guys! --- OpenSim/Services/MapImageService/MapImageService.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs index 736fa2ebac..27722bb4b7 100644 --- a/OpenSim/Services/MapImageService/MapImageService.cs +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -23,6 +23,10 @@ * 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. + * + * The design of this map service is based on SimianGrid's PHP-based + * map service. See this URL for the original PHP version: + * https://github.com/openmetaversefoundation/simiangrid/ */ using System; From dc978d02a723440a3860da0ad6a2b61b09769f39 Mon Sep 17 00:00:00 2001 From: Michael Cerquoni aka Nebadon Izumi Date: Mon, 13 Jun 2011 03:46:24 -0700 Subject: [PATCH 174/186] match water color for warp3d map tiler and adjust lighting --- .../CoreModules/World/Warp3DMap/MapImageModule.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs index 6eb57eb424..6163fd12fe 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs @@ -52,7 +52,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap public class Warp3DImageModule : IMapImageGenerator, INonSharedRegionModule { private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3"); - private static readonly Color4 WATER_COLOR = new Color4(29, 71, 95, 216); + private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap private IRendering m_primMesher; private IConfigSource m_config; private Dictionary m_colors = new Dictionary(); - private bool m_useAntiAliasing = true; // TODO: Make this a config option + private bool m_useAntiAliasing = false; // TODO: Make this a config option private bool m_Enabled = false; #region IRegionModule Members @@ -192,8 +192,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap #endregion Camera - renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(0.2f, 0.2f, 1f), 0xffffff, 320, 80)); - renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 100, 40)); + renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(1.0f, 0.5f, 1f), 0xffffff, 0, 320, 40)); + renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40)); CreateWater(renderer); CreateTerrain(renderer, textureTerrain); @@ -237,6 +237,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap renderer.Scene.sceneobject("Water").setPos(127.5f, waterHeight, 127.5f); renderer.AddMaterial("WaterColor", ConvertColor(WATER_COLOR)); + renderer.Scene.material("WaterColor").setReflectivity(0); // match water color with standard map module thanks lkalif renderer.Scene.material("WaterColor").setTransparency((byte)((1f - WATER_COLOR.A) * 255f)); renderer.SetObjectMaterial("Water", "WaterColor"); } @@ -322,6 +323,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap warp_Material material = new warp_Material(texture); material.setReflectivity(50); renderer.Scene.addMaterial("TerrainColor", material); + renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif renderer.SetObjectMaterial("Terrain", "TerrainColor"); } @@ -653,4 +655,4 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap return result; } } -} +} \ No newline at end of file From 0e4db3ca3911d8ac7080f51931ffe71b388e7180 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 13 Jun 2011 07:56:52 -0700 Subject: [PATCH 175/186] Added experimental new capability URL called MapImageService meant to work with Kokua viewer if devs are willing to do it. --- .../ClientStack/Linden/Caps/MiscCapsModule.cs | 119 ++++++++++++++++++ bin/OpenSim.ini.example | 5 + 2 files changed, 124 insertions(+) create mode 100644 OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs new file mode 100644 index 0000000000..d084a738d5 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs @@ -0,0 +1,119 @@ +/* + * 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.Reflection; +using log4net; +using Nini.Config; +using Mono.Addins; +using OpenMetaverse; +using OpenSim.Framework; +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 +{ + /// + /// A module to place miscellaneous capabilities + /// + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class MiscCapsModule : INonSharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + + private bool m_Enabled = false; + private string m_MapImageServerURL; + + #region ISharedRegionModule Members + + public void Initialise(IConfigSource source) + { + m_Enabled = true; + IConfig config = source.Configs["ClientStack.LindenCaps"]; + if (config == null) + return; + + m_MapImageServerURL = config.GetString("Cap_MapImageService", string.Empty); + } + + 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_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void PostInitialise() + { + } + + public void Close() { } + + public string Name { get { return "MiscCapsModule"; } } + + public Type ReplaceableInterface + { + get { return null; } + } + + #endregion + + public void RegisterCaps(UUID agentID, Caps caps) + { + m_log.InfoFormat("[MISC CAPS MODULE]: {0} in region {1}", m_MapImageServerURL, m_scene.RegionInfo.RegionName); + if (m_MapImageServerURL != string.Empty) + caps.RegisterHandler("MapImageService", m_MapImageServerURL); + } + + } +} diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 813c5b828c..a9ce2841fc 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -306,6 +306,11 @@ ; 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 = "" + ; Experimental new capability for Kokua viewers meant to override + ; the MapImage server url given at login, and varying switching on + ; a sim-basis (as it should). + ; Viewers that don't understand it, will ignore it + Cap_MapImageService = "http://127.0.0.1:9000/ [Chat] ;# {whisper_distance} {} {Distance at which a whisper is heard, in meters?} {} 10 From ab11835aeb341a34f479d9a6eb18de1ca9500c4a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 13 Jun 2011 07:59:28 -0700 Subject: [PATCH 176/186] Same processing of the "/" in the MapImageService Cap as the one in the login service. --- OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs index d084a738d5..3dcd1e3a11 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs @@ -66,6 +66,12 @@ namespace OpenSim.Region.ClientStack.Linden return; m_MapImageServerURL = config.GetString("Cap_MapImageService", string.Empty); + if (m_MapImageServerURL != string.Empty) + { + m_MapImageServerURL = m_MapImageServerURL.Trim(); + if (!m_MapImageServerURL.EndsWith("/")) + m_MapImageServerURL = m_MapImageServerURL + "/"; + } } public void AddRegion(Scene s) From ecb28ae130d1fc212c72af887fc75ae2bf64ab97 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 13 Jun 2011 09:13:44 -0700 Subject: [PATCH 177/186] V2 map now working in grids too. WARNING: A few visible configuration variables added in order for this to work. See .ini.example changes --- .../Handlers/Map/MapAddServerConnector.cs | 124 +++++++++++++++++- .../Handlers/Map/MapGetServerConnector.cs | 1 - .../MapImage/MapImageServiceConnector.cs | 81 ++++++------ .../MapImageService/MapImageService.cs | 2 +- bin/Robust.HG.ini.example | 8 +- bin/Robust.ini.example | 9 +- bin/config-include/Grid.ini | 6 + bin/config-include/GridCommon.ini.example | 3 + bin/config-include/GridHypergrid.ini | 8 +- 9 files changed, 193 insertions(+), 49 deletions(-) diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs index a953cd7eaf..99f98b60d7 100644 --- a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs @@ -26,7 +26,14 @@ */ using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; + using Nini.Config; +using log4net; + using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenSim.Framework.Servers.HttpServer; @@ -55,7 +62,122 @@ namespace OpenSim.Server.Handlers.MapImage Object[] args = new Object[] { config }; m_MapService = ServerUtils.LoadPlugin(gridService, args); - //server.AddStreamHandler(new PresenceServerPostHandler(m_PresenceService)); + server.AddStreamHandler(new MapServerPostHandler(m_MapService)); + } + } + + class MapServerPostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IMapImageService m_MapService; + + public MapServerPostHandler(IMapImageService service) : + base("POST", "/map") + { + m_MapService = service; + } + + public override byte[] Handle(string path, Stream requestData, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: Received {0}", path); + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + try + { + Dictionary request = ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("X") || !request.ContainsKey("Y") || !request.ContainsKey("DATA")) + { + httpResponse.StatusCode = (int)OSHttpStatusCode.ClientErrorBadRequest; + return FailureResult("Bad request."); + } + int x = 0, y = 0; + Int32.TryParse(request["X"].ToString(), out x); + Int32.TryParse(request["Y"].ToString(), out y); + string type = "image/jpeg"; + if (request.ContainsKey("TYPE")) + type = request["TYPE"].ToString(); + byte[] data = Convert.FromBase64String(request["DATA"].ToString()); + + string reason = string.Empty; + bool result = m_MapService.AddMapTile(x, y, data, out reason); + + if (result) + return SuccessResult(); + else + return FailureResult(reason); + + } + catch (Exception e) + { + m_log.ErrorFormat("[MAP SERVICE IMAGE HANDLER]: Exception {0} {1}", e.Message, e.StackTrace); + } + + return FailureResult("Unexpected server error"); + + } + + private byte[] SuccessResult() + { + 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("Success")); + + rootElement.AppendChild(result); + + return DocToBytes(doc); + } + + private byte[] FailureResult(string msg) + { + 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("Failure")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Message", ""); + message.AppendChild(doc.CreateTextNode(msg)); + + rootElement.AppendChild(message); + + 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(); } } } diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs index 53d08faa3b..e8a424f513 100644 --- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -80,7 +80,6 @@ namespace OpenSim.Server.Handlers.MapImage public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { - m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: retrieving {0}", path); byte[] result = new byte[0]; string format = string.Empty; diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs index ff0e9d9aee..520d639ccf 100644 --- a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs +++ b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs @@ -36,6 +36,7 @@ using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Framework.Communications; +using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -83,60 +84,57 @@ namespace OpenSim.Services.Connectors throw new Exception("MapImage connector init error"); } m_ServerURI = serviceURI; + m_ServerURI = serviceURI.TrimEnd('/'); } - public bool AddMapTile(int x, int y, byte[] pngData, out string reason) + public bool AddMapTile(int x, int y, byte[] jpgData, out string reason) { - List postParameters = new List() - { - new MultipartForm.Parameter("X", x.ToString()), - new MultipartForm.Parameter("Y", y.ToString()), - new MultipartForm.File("Tile", "tile.png", "image/png", pngData) - }; - - reason = string.Empty; + 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); - // Make the remote storage request try { - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI); - request.Timeout = 20000; - request.ReadWriteTimeout = 5000; - - using (HttpWebResponse response = MultipartForm.Post(request, postParameters)) + string reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/map", + reqString); + if (reply != string.Empty) { - using (Stream responseStream = response.GetResponseStream()) + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "success")) { - string responseStr = responseStream.GetStreamString(); - OSD responseOSD = OSDParser.Deserialize(responseStr); - if (responseOSD.Type == OSDType.Map) - { - OSDMap responseMap = (OSDMap)responseOSD; - if (responseMap["Success"].AsBoolean()) - return true; - - reason = "Upload failed: " + responseMap["Message"].AsString(); - } - else - { - reason = "Response format was invalid:\n" + responseStr; - } + return true; } + else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure")) + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Registration failed: {0}", replyData["Message"].ToString()); + reason = replyData["Message"].ToString(); + return false; + } + else if (!replyData.ContainsKey("Result")) + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: reply data does not contain result field"); + } + else + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: unexpected result {0}", replyData["Result"].ToString()); + reason = "Unexpected result " + replyData["Result"].ToString(); + } + } + else + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: RegisterRegion received null reply"); } - catch (WebException we) + catch (Exception e) { - reason = we.Message; - if (we.Status == WebExceptionStatus.ProtocolError) - { - HttpWebResponse webResponse = (HttpWebResponse)we.Response; - reason = String.Format("[{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription); - } - } - catch (Exception ex) - { - reason = ex.Message; + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Exception when contacting grid server: {0}", e.Message); } finally { @@ -146,6 +144,7 @@ namespace OpenSim.Services.Connectors } return false; + } public byte[] GetMapTile(string fileName, out string format) diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs index 27722bb4b7..7e7391c988 100644 --- a/OpenSim/Services/MapImageService/MapImageService.cs +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -143,7 +143,7 @@ namespace OpenSim.Services.MapImageService if (File.Exists(fullName)) { format = Path.GetExtension(fileName).ToLower(); - m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format); + //m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format); return File.ReadAllBytes(fullName); } else if (File.Exists(m_WaterTileFile)) diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 812d2659fa..00ece88025 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -21,7 +21,7 @@ ; * [[@]/][:] ; * [Startup] -ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector" +ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" ; * This is common for all services, it's the network setup for the entire ; * server instance, if none is specified above @@ -206,6 +206,9 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 WelcomeMessage = "Welcome, Avatar!" AllowRemoteSetLoginLevel = "false" + ; For V2 map + ; MapTileURL = "http://127.0.0.1:8002"; + ; If you run this login server behind a proxy, set this to true ; HasProxy = false @@ -237,6 +240,9 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ;AllowedClients = "" ;DeniedClients = "" +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + [GridInfoService] ; These settings are used to return information on a get_grid_info call. ; Client launcher scripts and third-party clients make use of this to diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index 5d0ec09d7d..e29e9dbbc7 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example @@ -13,7 +13,7 @@ ; * [[@]/][:] ; * [Startup] -ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector" +ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" ; * This is common for all services, it's the network setup for the entire ; * server instance, if none is specified above @@ -191,8 +191,8 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 WelcomeMessage = "Welcome, Avatar!" AllowRemoteSetLoginLevel = "false" - ; For snowglobe's web map - ; MapTileURL = ""; + ; For V2 map + ; MapTileURL = "http://127.0.0.1:8002"; ; If you run this login server behind a proxy, set this to true ; HasProxy = false @@ -214,6 +214,9 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ;AllowedClients = "" ;DeniedClients = "" +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + [GridInfoService] ; These settings are used to return information on a get_grid_info call. ; Client launcher scripts and third-party clients make use of this to diff --git a/bin/config-include/Grid.ini b/bin/config-include/Grid.ini index 52205732f0..da860c6859 100644 --- a/bin/config-include/Grid.ini +++ b/bin/config-include/Grid.ini @@ -21,6 +21,7 @@ EntityTransferModule = "BasicEntityTransferModule" InventoryAccessModule = "BasicInventoryAccessModule" LandServices = "RemoteLandServicesConnector" + MapImageService = "MapImageServiceModule" LandServiceInConnector = true NeighbourServiceInConnector = true @@ -50,3 +51,8 @@ [Friends] Connector = "OpenSim.Services.Connectors.dll:FriendsServicesConnector" + +[MapImageService] + LocalServiceModule = "OpenSim.Services.Connectors.dll:MapImageServicesConnector" + ; in minutes + RefreshTime = 60 diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index 27f262f374..4eb6fcf333 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -116,6 +116,9 @@ ; UserAgentServerURI = "http://mygridserver.com:8002" +[MapImageService] + MapImageServerURI = "http://mygridserver.com:8003" + [Modules] ;; Choose 0 or 1 cache modules, and the corresponding config file, if it exists. ;; Copy the config .example file into your own .ini file and change configs there diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index b8e66c2733..60a3c625f2 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -25,6 +25,7 @@ InventoryAccessModule = "HGInventoryAccessModule" LandServices = "RemoteLandServicesConnector" FriendsModule = "HGFriendsModule" + MapImageService = "MapImageServiceModule" LandServiceInConnector = true NeighbourServiceInConnector = true @@ -76,4 +77,9 @@ LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" GridService = "OpenSim.Services.Connectors.dll:GridServicesConnector" PresenceService = "OpenSim.Services.Connectors.dll:PresenceServicesConnector" - UserAgentService = "OpenSim.Services.Connectors.dll:UserAgentServiceConnector" \ No newline at end of file + UserAgentService = "OpenSim.Services.Connectors.dll:UserAgentServiceConnector" + +[MapImageService] + LocalServiceModule = "OpenSim.Services.Connectors.dll:MapImageServicesConnector" + ; in minutes + RefreshTime = 60 From 822b9e085fca9dcf04e61b29b98daeecf7893d85 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 13 Jun 2011 10:21:29 -0700 Subject: [PATCH 178/186] Added SimulatorFeatures capability. Thanks Aurora devs for the bootstrap on the contents of the response. Changed the experimental capability introduced a couple of commits ago: now sending that extra information as part of the response in the SimulatorFeatures cap. --- ...psModule.cs => SimulatorFeaturesModule.cs} | 71 +++++++++++++------ bin/OpenSim.ini.example | 11 +-- 2 files changed, 56 insertions(+), 26 deletions(-) rename OpenSim/Region/ClientStack/Linden/Caps/{MiscCapsModule.cs => SimulatorFeaturesModule.cs} (59%) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs similarity index 59% rename from OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs rename to OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs index 3dcd1e3a11..9f78948df4 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs @@ -32,71 +32,67 @@ using log4net; using Nini.Config; using Mono.Addins; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Framework; 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 { /// - /// A module to place miscellaneous capabilities + /// SimulatorFeatures capability. This is required for uploading Mesh. + /// Since is accepts an open-ended response, we also send more information + /// for viewers that care to interpret it. + /// + /// NOTE: Part of this code was adapted from the Aurora project, specifically + /// the normal part of the response in the capability handler. /// /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class MiscCapsModule : INonSharedRegionModule + public class SimulatorFeaturesModule : ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; - private bool m_Enabled = false; - private string m_MapImageServerURL; + private string m_MapImageServerURL = string.Empty; + private string m_SearchURL = string.Empty; #region ISharedRegionModule Members public void Initialise(IConfigSource source) { - m_Enabled = true; - IConfig config = source.Configs["ClientStack.LindenCaps"]; + IConfig config = source.Configs["SimulatorFeatures"]; if (config == null) return; - m_MapImageServerURL = config.GetString("Cap_MapImageService", string.Empty); + m_MapImageServerURL = config.GetString("MapImageServerURI", string.Empty); if (m_MapImageServerURL != string.Empty) { m_MapImageServerURL = m_MapImageServerURL.Trim(); if (!m_MapImageServerURL.EndsWith("/")) m_MapImageServerURL = m_MapImageServerURL + "/"; } + + m_SearchURL = config.GetString("SearchServerURI", string.Empty); } public void AddRegion(Scene s) { - if (!m_Enabled) - return; - m_scene = s; + m_scene.EventManager.OnRegisterCaps += RegisterCaps; } 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_scene.EventManager.OnRegisterCaps += RegisterCaps; } public void PostInitialise() @@ -105,7 +101,7 @@ namespace OpenSim.Region.ClientStack.Linden public void Close() { } - public string Name { get { return "MiscCapsModule"; } } + public string Name { get { return "SimulatorFeaturesModule"; } } public Type ReplaceableInterface { @@ -116,9 +112,40 @@ namespace OpenSim.Region.ClientStack.Linden public void RegisterCaps(UUID agentID, Caps caps) { - m_log.InfoFormat("[MISC CAPS MODULE]: {0} in region {1}", m_MapImageServerURL, m_scene.RegionInfo.RegionName); + IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), SimulatorFeatures); + caps.RegisterHandler("SimulatorFeatures", reqHandler); + } + + private Hashtable SimulatorFeatures(Hashtable mDhttpMethod) + { + m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request"); + OSDMap data = new OSDMap(); + data["MeshRezEnabled"] = true; + data["MeshUploadEnabled"] = true; + data["MeshXferEnabled"] = true; + data["PhysicsMaterialsEnabled"] = true; + + OSDMap typesMap = new OSDMap(); + typesMap["convex"] = true; + typesMap["none"] = true; + typesMap["prim"] = true; + data["PhysicsShapeTypes"] = typesMap; + + // Extra information for viewers that want to use it + OSDMap gridServicesMap = new OSDMap(); if (m_MapImageServerURL != string.Empty) - caps.RegisterHandler("MapImageService", m_MapImageServerURL); + gridServicesMap["map-server-url"] = m_MapImageServerURL; + if (m_SearchURL != string.Empty) + gridServicesMap["search"] = m_SearchURL; + data["GridServices"] = gridServicesMap; + + //Send back data + Hashtable responsedata = new Hashtable(); + responsedata["int_response_code"] = 200; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(data); + return responsedata; } } diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index a9ce2841fc..bab118fd63 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -306,11 +306,14 @@ ; 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 = "" - ; Experimental new capability for Kokua viewers meant to override - ; the MapImage server url given at login, and varying switching on - ; a sim-basis (as it should). + +[SimulatorFeatures] + ; Experimental new information sent in SimulatorFeatures cap for Kokua viewers + ; meant to override the MapImage and search server url given at login, and varying + ; on a sim-basis. ; Viewers that don't understand it, will ignore it - Cap_MapImageService = "http://127.0.0.1:9000/ + ;MapImageServerURI = "http://127.0.0.1:9000/ + ;SearchServerURI = "http://127.0.0.1:9000/ [Chat] ;# {whisper_distance} {} {Distance at which a whisper is heard, in meters?} {} 10 From 603dbea190de26dce5160f5ab9730ffc1375ec26 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 14 Jun 2011 00:51:18 +0100 Subject: [PATCH 179/186] tweak messages. Make verbose inventory item save message give the item name as well as item id and asset id --- .../Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | 4 +++- OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index c2ad079536..36ecb3b7ee 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -147,7 +147,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary options, IUserAccountService userAccountService) { if (options.ContainsKey("verbose")) - m_log.InfoFormat("[INVENTORY ARCHIVER]: Saving item {0} with asset {1}", inventoryItem.ID, inventoryItem.AssetID); + m_log.InfoFormat( + "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", + inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); string filename = path + CreateArchiveItemName(inventoryItem); diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index 3078ab384e..6a9c3d016d 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -198,11 +198,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.ErrorFormat( "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT); - m_log.Error("[ARCHIVER]: OAR save aborted. PLEASE DO NOT USE THIS OAR, IT WILL BE INCOMPLETE."); + m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE."); } catch (Exception e) { - m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}", e); + m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace); } finally { From bbe489e64a4c1bfdae591f3b6cf60ee0b1809176 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 15 Jun 2011 11:11:14 -0700 Subject: [PATCH 180/186] Added missing config var for map image service. --- bin/Robust.HG.ini.example | 2 ++ bin/Robust.ini.example | 3 +++ bin/config-include/StandaloneCommon.ini.example | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 00ece88025..ea271b864a 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -242,6 +242,8 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 [MapImageService] LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; Set this if you want to change the default + ; TilesStoragePath = "maptiles" [GridInfoService] ; These settings are used to return information on a get_grid_info call. diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index e29e9dbbc7..14f79aac14 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example @@ -216,6 +216,9 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 [MapImageService] LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; Set this if you want to change the default + ; TilesStoragePath = "maptiles" + [GridInfoService] ; These settings are used to return information on a get_grid_info call. diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 29c2af1f96..cbe3fa0aef 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -223,3 +223,7 @@ ; password help: optional: page providing password assistance for users of your grid ; currently unused ;password = http://127.0.0.1/password + +[MapImageService] + ; Set this if you want to change the default + ; TilesStoragePath = "maptiles" From 7a4fbdac7c18415d442f6af0b75fe8fcdc2eb509 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Wed, 15 Jun 2011 11:22:51 -0700 Subject: [PATCH 181/186] Added an expiring cache for region information to the RemoteGridService connector. Timeout is currently set at five minutes. Negative results are not cached. The result is that operations like send an instant message do not have to go through the grid service every time. --- .../Grid/RegionInfoCache.cs | 137 ++++++++++++++++++ .../Grid/RemoteGridServiceConnector.cs | 34 ++++- 2 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs new file mode 100644 index 0000000000..786e0b5737 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs @@ -0,0 +1,137 @@ +/* + * 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.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenMetaverse; +using log4net; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid +{ + public class RegionInfoCache + { + private const double CACHE_EXPIRATION_SECONDS = 300.0; // 5 minutes + +// private static readonly ILog m_log = +// LogManager.GetLogger( +// MethodBase.GetCurrentMethod().DeclaringType); + + internal struct ScopedRegionUUID + { + public UUID m_scopeID; + public UUID m_regionID; + public ScopedRegionUUID(UUID scopeID, UUID regionID) + { + m_scopeID = scopeID; + m_regionID = regionID; + } + } + + internal struct ScopedRegionName + { + public UUID m_scopeID; + public string m_name; + public ScopedRegionName(UUID scopeID, string name) + { + m_scopeID = scopeID; + m_name = name; + } + } + + private ExpiringCache m_UUIDCache; + private ExpiringCache m_NameCache; + + public RegionInfoCache() + { + m_UUIDCache = new ExpiringCache(); + m_NameCache = new ExpiringCache(); + } + + public void Cache(GridRegion rinfo) + { + if (rinfo != null) + this.Cache(rinfo.ScopeID,rinfo.RegionID,rinfo); + } + + public void Cache(UUID scopeID, UUID regionID, GridRegion rinfo) + { + // for now, do not cache negative results; this is because + // we need to figure out how to handle regions coming online + // in a timely way + if (rinfo == null) + return; + + ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID); + + // Cache even null accounts + m_UUIDCache.AddOrUpdate(id, rinfo, CACHE_EXPIRATION_SECONDS); + if (rinfo != null) + { + ScopedRegionName name = new ScopedRegionName(scopeID,rinfo.RegionName); + m_NameCache.AddOrUpdate(name, id, CACHE_EXPIRATION_SECONDS); + } + } + + public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache) + { + inCache = false; + + GridRegion rinfo = null; + ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID); + if (m_UUIDCache.TryGetValue(id, out rinfo)) + { + inCache = true; + return rinfo; + } + + return null; + } + + public GridRegion Get(UUID scopeID, string name, out bool inCache) + { + inCache = false; + + ScopedRegionName sname = new ScopedRegionName(scopeID,name); + + ScopedRegionUUID id; + if (m_NameCache.TryGetValue(sname, out id)) + { + GridRegion rinfo = null; + if (m_UUIDCache.TryGetValue(id, out rinfo)) + { + inCache = true; + return rinfo; + } + } + + return null; + } + } +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs index 33cc838322..6f364ae4c8 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs @@ -53,6 +53,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid private IGridService m_LocalGridService; private IGridService m_RemoteGridService; + private RegionInfoCache m_RegionInfoCache = new RegionInfoCache(); + public RemoteGridServicesConnector() { } @@ -169,10 +171,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) { - GridRegion rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID); + bool inCache = false; + GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache); + if (inCache) + return rinfo; + + rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID); if (rinfo == null) rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID); + m_RegionInfoCache.Cache(scopeID,regionID,rinfo); return rinfo; } @@ -187,10 +195,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public GridRegion GetRegionByName(UUID scopeID, string regionName) { - GridRegion rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName); + bool inCache = false; + GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionName, out inCache); + if (inCache) + return rinfo; + + rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName); if (rinfo == null) rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName); + // can't cache negative results for name lookups + m_RegionInfoCache.Cache(rinfo); return rinfo; } @@ -204,8 +219,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetRegionsByName {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -221,8 +239,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetRegionRange {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -238,8 +259,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetDefaultRegions {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -255,8 +279,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetFallbackRegions {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; @@ -272,8 +299,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetHyperlinks {0} found {1} regions", name, grinfo.Count); foreach (GridRegion r in grinfo) + { + m_RegionInfoCache.Cache(r); if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) rinfo.Add(r); + } } return rinfo; From 29da57e3802948bbffce43c071e6c97742cabf84 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Wed, 15 Jun 2011 11:26:45 -0700 Subject: [PATCH 182/186] Add the PhysActor to the correct SOP when duplicating a physical prim. Thanks, MisterBlue --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 79660a3d11..f745169b78 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1449,18 +1449,23 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart part in partList) { + SceneObjectPart newPart; if (part.UUID != m_rootPart.UUID) { - SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); + newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); newPart.LinkNum = part.LinkNum; } + else + { + newPart = dupe.m_rootPart; + } // Need to duplicate the physics actor as well if (part.PhysActor != null && userExposed) { PrimitiveBaseShape pbs = part.Shape; - part.PhysActor + newPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( string.Format("{0}/{1}", part.Name, part.UUID), pbs, @@ -1469,8 +1474,8 @@ namespace OpenSim.Region.Framework.Scenes part.RotationOffset, part.PhysActor.IsPhysical); - part.PhysActor.LocalID = part.LocalId; - part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); + newPart.PhysActor.LocalID = part.LocalId; + newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); } } From ad84728aba1ea5efe0d237c89e1578657e6d8288 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Wed, 15 Jun 2011 11:31:32 -0700 Subject: [PATCH 183/186] Add localID to physical object creation functions. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- .../Region/Framework/Scenes/SceneObjectPart.cs | 4 ++-- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- OpenSim/Region/Physics/Manager/PhysicsActor.cs | 7 ++++++- OpenSim/Region/Physics/Manager/PhysicsScene.cs | 15 +++++++++++++++ 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f745169b78..42ac9aa26b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1467,6 +1467,7 @@ namespace OpenSim.Region.Framework.Scenes newPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( + part.LocalId, string.Format("{0}/{1}", part.Name, part.UUID), pbs, part.AbsolutePosition, @@ -1474,7 +1475,6 @@ namespace OpenSim.Region.Framework.Scenes part.RotationOffset, part.PhysActor.IsPhysical); - newPart.PhysActor.LocalID = part.LocalId; newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index a215b20234..c6d8c73015 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1582,6 +1582,7 @@ namespace OpenSim.Region.Framework.Scenes if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) { PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( + LocalId, string.Format("{0}/{1}", Name, UUID), Shape, AbsolutePosition, @@ -1594,7 +1595,6 @@ namespace OpenSim.Region.Framework.Scenes { PhysActor.SOPName = this.Name; // save object name and desc into the PhysActor so ODE internals know the joint/body info PhysActor.SOPDescription = this.Description; - PhysActor.LocalID = LocalId; DoPhysicsPropertyUpdate(RigidBody, true); PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); } @@ -4410,6 +4410,7 @@ namespace OpenSim.Region.Framework.Scenes { // It's not phantom anymore. So make sure the physics engine get's knowledge of it PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( + LocalId, string.Format("{0}/{1}", Name, UUID), Shape, AbsolutePosition, @@ -4420,7 +4421,6 @@ namespace OpenSim.Region.Framework.Scenes pa = PhysActor; if (pa != null) { - pa.LocalID = LocalId; DoPhysicsPropertyUpdate(UsePhysics, true); if (m_parentGroup != null) { diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index f6295b176d..80aafd0733 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3295,7 +3295,7 @@ namespace OpenSim.Region.Framework.Scenes Vector3 pVec = AbsolutePosition; // Old bug where the height was in centimeters instead of meters - m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, + m_physicsActor = scene.AddAvatar(LocalId, Firstname + "." + Lastname, pVec, new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); scene.AddPhysicsActorTaint(m_physicsActor); diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 880c3ea3cb..1c36e55b95 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -142,7 +142,12 @@ namespace OpenSim.Region.Physics.Manager public abstract PrimitiveBaseShape Shape { set; } - public abstract uint LocalID { set; } + uint m_baseLocalID; + public virtual uint LocalID + { + set { m_baseLocalID = value; } + get { return m_baseLocalID; } + } public abstract bool Grabbed { set; } diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 217d307443..54c50f8eda 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -66,6 +66,13 @@ namespace OpenSim.Region.Physics.Manager public abstract PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying); + public virtual PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, bool isFlying) + { + PhysicsActor ret = AddAvatar(avName, position, size, isFlying); + if (ret != null) ret.LocalID = localID; + return ret; + } + public abstract void RemoveAvatar(PhysicsActor actor); public abstract void RemovePrim(PhysicsActor prim); @@ -75,6 +82,14 @@ namespace OpenSim.Region.Physics.Manager public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical); + public virtual PhysicsActor AddPrimShape(uint localID, string primName, PrimitiveBaseShape pbs, Vector3 position, + Vector3 size, Quaternion rotation, bool isPhysical) + { + PhysicsActor ret = AddPrimShape(primName, pbs, position, size, rotation, isPhysical); + if (ret != null) ret.LocalID = localID; + return ret; + } + public virtual float TimeDilation { get { return 1.0f; } From 8791e5dac06725826a96ae2c115e10a8a1b2b57f Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Wed, 15 Jun 2011 13:43:02 -0700 Subject: [PATCH 184/186] Working out merge errors with master --- .../Avatar/InstantMessage/HGMessageTransferModule.cs | 6 ++++++ .../RegionSync/RegionSyncModule/RegionSyncAvatar.cs | 2 +- .../Framework/Scenes/Serialization/SceneObjectSerializer.cs | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs index 7753c259b3..d457257e83 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs @@ -222,6 +222,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage }); return; + } + + //DSG: make this function public, so that we can call from outside to + //use the Grid Service to send the instant message. + public virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) + { } protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID) diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncAvatar.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncAvatar.cs index c7f56f257b..03498ec202 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncAvatar.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncAvatar.cs @@ -615,7 +615,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_log.Debug("[REGION SYNC AVATAR] AttachObject"); } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { IGridDialogModule gridDialogModule = m_scene.RequestModuleInterface(); diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 3db6a9b1a0..f532135bea 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -1558,7 +1558,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// The shape parsed //DSG SYNC: make it public to be called outside //static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors) - public PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors) + public static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors) { errors = false; From 66f905b09c734995f779ed7dac736dd0aad59aa9 Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Wed, 15 Jun 2011 15:05:17 -0700 Subject: [PATCH 185/186] Fixed up merge conflicts from master due to changes in sending IMs between DSG regions --- .../InstantMessage/MessageTransferModule.cs | 24 ++----------------- .../RegionSyncModule/RegionSyncAvatar.cs | 2 +- .../SymmetricSync/GridDialogModule.cs | 22 ++++++++++------- .../SymmetricSync/RegionSyncModule.cs | 5 ++-- .../Framework/Interfaces/IGridDialogModule.cs | 2 +- 5 files changed, 20 insertions(+), 35 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index b88bdbb2b7..2778b5c5c1 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -48,8 +48,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage private bool m_Enabled = false; protected List m_Scenes = new List(); - protected Dictionary m_UserRegionMap = new Dictionary(); - protected Dictionary m_RegionInfoMap = new Dictionary(); + protected Dictionary m_UserRegionMap = new Dictionary(); public event UndeliveredMessage OnUndeliveredMessage; @@ -537,19 +536,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage if (upd != null) { - GridRegion reginfo = null; - // Try to pull reginfo from our cache - lock (m_RegionInfoMap) - { - if (!m_RegionInfoMap.TryGetValue(upd.RegionID, out reginfo)) - reginfo = null; - } - - // If it wasn't there, then look it up from grid. - if (reginfo == null) - { - reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID); - } + GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID); // If we found the reginfo, send the IM to the region if (reginfo != null) @@ -573,13 +560,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { m_UserRegionMap.Add(toAgentID, upd.RegionID); } - } - lock (m_RegionInfoMap) - { - // Since we never look it up again, we don't need to update it - // but if it's not in the map yet, add it now. - if (!m_RegionInfoMap.ContainsKey(upd.RegionID)) - m_RegionInfoMap.Add(upd.RegionID, reginfo); } result(true); } diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncAvatar.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncAvatar.cs index 03498ec202..cfd48fc544 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncAvatar.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncAvatar.cs @@ -621,7 +621,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule if (gridDialogModule != null) { - gridDialogModule.SendGridDialogViaXMLRPC(this.AgentId, objectname, objectID, ownerFirstName, ownerLastName, + gridDialogModule.SendGridDialogViaXMLRPC(this.AgentId, objectname, objectID, ownerID, ownerFirstName, ownerLastName, msg, textureID, ch, buttonlabels, UUID.Zero); } } diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/GridDialogModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/GridDialogModule.cs index 149831bf6c..b355393f5a 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/GridDialogModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/GridDialogModule.cs @@ -126,7 +126,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule #region GridCommunication - public delegate void GridDialogDelegate(UUID avatarID, string objectName, UUID objectID, string ownerFirstName, + public delegate void GridDialogDelegate(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID); protected virtual void GridDialogCompleted(IAsyncResult iar) @@ -136,17 +136,17 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule icon.EndInvoke(iar); } - public void SendGridDialogViaXMLRPC(UUID avatarID, string objectName, UUID objectID, string ownerFirstName, + public void SendGridDialogViaXMLRPC(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID) { GridDialogDelegate d = SendGridDialogViaXMLRPCAsync; - d.BeginInvoke(avatarID, objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels, prevRegionID, + d.BeginInvoke(avatarID, objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels, prevRegionID, GridDialogCompleted, d); } - private void SendGridDialogViaXMLRPCAsync(UUID avatarID, string objectName, UUID objectID, string ownerFirstName, + private void SendGridDialogViaXMLRPCAsync(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID) { PresenceInfo upd = null; @@ -190,7 +190,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule upd.RegionID); if (reginfo != null) { - Hashtable msgdata = ConvertGridDialogToXMLRPC(avatarID, objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); + Hashtable msgdata = ConvertGridDialogToXMLRPC(avatarID, objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); //= ConvertGridInstantMessageToXMLRPC(im); // Not actually used anymore, left in for compatibility // Remove at next interface change @@ -200,19 +200,20 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule bool imresult = doDialogSending(reginfo, msgdata); if (!imresult) { - SendGridDialogViaXMLRPCAsync(avatarID, objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels, prevRegionID); + SendGridDialogViaXMLRPCAsync(avatarID, objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels, prevRegionID); } } } } - private Hashtable ConvertGridDialogToXMLRPC(UUID avatarID, string objectName, UUID objectID, string ownerFirstName, string ownerLastName, + private Hashtable ConvertGridDialogToXMLRPC(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels) { Hashtable msgdata = new Hashtable(); msgdata["avatarID"] = avatarID.ToString(); msgdata["objectName"] = objectName; - msgdata["objectID"] = objectID.ToString(); + msgdata["objectID"] = objectID.ToString(); + msgdata["ownerID"] = ownerID.ToString(); msgdata["ownerFirstName"] = ownerFirstName; msgdata["ownerLastName"] = ownerLastName; msgdata["message"] = message; @@ -285,6 +286,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule UUID avatarID = UUID.Zero; UUID objectID = UUID.Zero; UUID textureID = UUID.Zero; + UUID ownerID = UUID.Zero; string objectName="", ownerFirstName="", ownerLastName=""; string message=""; int ch=0; @@ -295,6 +297,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule // Check if it's got all the data if (requestData.ContainsKey("avatarID") && requestData.ContainsKey("objectName") && requestData.ContainsKey("objectID") + && requestData.ContainsKey("ownerID") && requestData.ContainsKey("ownerFirstName") && requestData.ContainsKey("ownerLastName") && requestData.ContainsKey("message") && requestData.ContainsKey("textureID") && requestData.ContainsKey("ch") @@ -306,6 +309,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule UUID.TryParse((string)requestData["avatarID"], out avatarID); UUID.TryParse((string)requestData["objectID"], out objectID); UUID.TryParse((string)requestData["textureID"], out textureID); + UUID.TryParse((string)requestData["ownerID"], out ownerID); objectName = (string)requestData["objectName"]; ownerFirstName = (string)requestData["ownerFirstName"]; @@ -349,7 +353,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule if (!user.IsChildAgent) { - user.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); + user.ControllingClient.SendDialog(objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); deliverSuccessful = true; } } diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index 4e279dae47..c952f813e7 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -4069,8 +4069,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule XmlTextReader reader = new XmlTextReader(sr); PrimitiveBaseShape shapeValue; try - { - shapeValue = SceneObjectSerializer.ReadShape(reader, "Shape"); + { + bool errors = false; + shapeValue = SceneObjectSerializer.ReadShape(reader, "Shape", out errors); } catch (Exception e) { diff --git a/OpenSim/Region/Framework/Interfaces/IGridDialogModule.cs b/OpenSim/Region/Framework/Interfaces/IGridDialogModule.cs index 55f7876273..102dea44a4 100755 --- a/OpenSim/Region/Framework/Interfaces/IGridDialogModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IGridDialogModule.cs @@ -35,7 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces { public interface IGridDialogModule { - void SendGridDialogViaXMLRPC(UUID avatarID, string objectName, UUID objectID, string ownerFirstName, string ownerLastName, + void SendGridDialogViaXMLRPC(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID); } } From 2c27067dec7febf5f6dba163d63d97bfd5c3ba1f Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Wed, 15 Jun 2011 15:38:16 -0700 Subject: [PATCH 186/186] Fixed typo in merge --- .../CoreModules/Avatar/InstantMessage/MessageTransferModule.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index f700e6fdb4..20dc639f17 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -535,7 +535,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } if (upd != null) -<<<<<<< HEAD { GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID);