From 7c229c8b812b0975133a2612b34225c7c9403f1b Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sun, 13 May 2012 17:11:44 -0400 Subject: [PATCH 1/9] Add configurable SpawnPointRouting Will use one of three selected methods to route avatar landing points when using Telehubs. The setting is in [Startup] using SpawnPointRouting = closest/random/sequence closest: The default setting. Routes avatar to the nearest SpawnPoint to the location. random: Picks random SpawnPoints to land the avatar. sequence: Follows a sequence to place the avatar on the next available SpawnPoint location Conflicts: OpenSim/Region/Framework/Scenes/Scene.cs --- OpenSim/Region/Framework/Scenes/Scene.cs | 81 ++++++++++---- .../Region/Framework/Scenes/ScenePresence.cs | 103 ++++++++++++++---- 2 files changed, 146 insertions(+), 38 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 3d2213a9cc..2a2830f47d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -569,6 +569,15 @@ namespace OpenSim.Region.Framework.Scenes get { return m_sceneGraph.Entities; } } + // can be closest/random/sequence + private string m_SpawnPointRouting = "closest"; + // used in sequence see: SpawnPoint() + private int m_SpawnPoint; + public string SpawnPointRouting + { + get { return m_SpawnPointRouting; } + } + #endregion Properties #region Constructors @@ -586,7 +595,7 @@ namespace OpenSim.Region.Framework.Scenes Random random = new Random(); - m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue/2))+(uint)(uint.MaxValue/4); + m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4); m_moduleLoader = moduleLoader; m_authenticateHandler = authen; m_sceneGridService = sceneGridService; @@ -678,7 +687,7 @@ namespace OpenSim.Region.Framework.Scenes { IConfig startupConfig = m_config.Configs["Startup"]; - m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); + 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); @@ -711,7 +720,7 @@ namespace OpenSim.Region.Framework.Scenes m_clampPrimSize = true; } - m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete); + m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); m_dontPersistBefore = @@ -723,6 +732,8 @@ namespace OpenSim.Region.Framework.Scenes m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); + m_SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); + IConfig packetConfig = m_config.Configs["PacketPool"]; if (packetConfig != null) { @@ -3389,7 +3400,7 @@ namespace OpenSim.Region.Framework.Scenes public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) { bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || - (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); + (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0); bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0); @@ -3405,8 +3416,17 @@ namespace OpenSim.Region.Framework.Scenes // Don't disable this log message - it's too helpful m_log.DebugFormat( "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", - RegionInfo.RegionName, (agent.child ? "child" : "root"),agent.firstname, agent.lastname, - agent.AgentID, agent.circuitcode, agent.IPAddress, agent.Viewer, ((TPFlags)teleportFlags).ToString(), agent.startpos); + RegionInfo.RegionName, + (agent.child ? "child" : "root"), + agent.firstname, + agent.lastname, + agent.AgentID, + agent.circuitcode, + agent.IPAddress, + agent.Viewer, + ((TPFlags)teleportFlags).ToString(), + agent.startpos + ); if (LoginsDisabled) { @@ -3421,7 +3441,11 @@ namespace OpenSim.Region.Framework.Scenes // We have a zombie from a crashed session. // Or the same user is trying to be root twice here, won't work. // Kill it. - m_log.DebugFormat("[SCENE]: Zombie scene presence detected for {0} in {1}", agent.AgentID, RegionInfo.RegionName); + m_log.DebugFormat( + "[SCENE]: Zombie scene presence detected for {0} in {1}", + agent.AgentID, + RegionInfo.RegionName + ); sp.ControllingClient.Close(); sp = null; } @@ -3445,8 +3469,7 @@ namespace OpenSim.Region.Framework.Scenes { if (!VerifyUserPresence(agent, out reason)) return false; - } - catch (Exception e) + } catch (Exception e) { m_log.ErrorFormat( "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); @@ -3458,8 +3481,7 @@ namespace OpenSim.Region.Framework.Scenes { if (!AuthorizeUser(agent, out reason)) return false; - } - catch (Exception e) + } catch (Exception e) { m_log.ErrorFormat( "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); @@ -3476,8 +3498,7 @@ namespace OpenSim.Region.Framework.Scenes CapsModule.SetAgentCapsSeeds(agent); CapsModule.CreateCaps(agent.AgentID); } - } - else + } else { // Let the SP know how we got here. This has a lot of interesting // uses down the line. @@ -3500,7 +3521,7 @@ namespace OpenSim.Region.Framework.Scenes agent.teleportFlags = teleportFlags; m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); - if (vialogin) + if (vialogin) { // CleanDroppedAttachments(); @@ -3541,8 +3562,7 @@ namespace OpenSim.Region.Framework.Scenes agent.startpos.Z = 720; } } - } - else + } else { if (agent.startpos.X > EastBorders[0].BorderLine.Z) { @@ -3568,10 +3588,19 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); // Can have multiple SpawnPoints List spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); - if ( spawnpoints.Count > 1) + if (spawnpoints.Count > 1) { - // We have multiple SpawnPoints, Route the agent to a random one - agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count)].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); + // We have multiple SpawnPoints, Route the agent to a random or sequential one + if (SpawnPointRouting == "random") + agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( + telehub.AbsolutePosition, + telehub.GroupRotation + ); + else + agent.startpos = spawnpoints[SpawnPoint()].GetLocation( + telehub.AbsolutePosition, + telehub.GroupRotation + ); } else { @@ -5257,5 +5286,19 @@ namespace OpenSim.Region.Framework.Scenes } } } + + // manage and select spawn points in sequence + public int SpawnPoint() + { + int spawnpoints = RegionInfo.RegionSettings.SpawnPoints().Count; + + if (spawnpoints == 0) + return 0; + + m_SpawnPoint++; + if (m_SpawnPoint > spawnpoints) + m_SpawnPoint = 1; + return m_SpawnPoint - 1; + } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b737f91f0f..bdcef71159 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3934,28 +3934,93 @@ namespace OpenSim.Region.Framework.Scenes if (spawnPoints.Length == 0) return; - float distance = 9999; - int closest = -1; + int index; + bool selected = false; - for (int i = 0 ; i < spawnPoints.Length ; i++) + switch (m_scene.SpawnPointRouting) { - Vector3 spawnPosition = spawnPoints[i].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); - Vector3 offset = spawnPosition - pos; - float d = Vector3.Mag(offset); - if (d >= distance) - continue; - ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y); - if (land == null) - continue; - if (land.IsEitherBannedOrRestricted(UUID)) - continue; - distance = d; - closest = i; - } - if (closest == -1) - return; + case "closest": - pos = spawnPoints[closest].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); + float distance = 9999; + int closest = -1; + + for (int i = 0; i < spawnPoints.Length; i++) + { + Vector3 spawnPosition = spawnPoints[i].GetLocation( + telehub.AbsolutePosition, + telehub.GroupRotation + ); + Vector3 offset = spawnPosition - pos; + float d = Vector3.Mag(offset); + if (d >= distance) + continue; + ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y); + if (land == null) + continue; + if (land.IsEitherBannedOrRestricted(UUID)) + continue; + distance = d; + closest = i; + } + if (closest == -1) + return; + + pos = spawnPoints[closest].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); + return; + + case "random": + + do + { + index = Util.RandomClass.Next(spawnPoints.Length - 1); + + Vector3 spawnPosition = spawnPoints[index].GetLocation( + telehub.AbsolutePosition, + telehub.GroupRotation + ); + // SpawnPoint sp = spawnPoints[index]; + + ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y); + if (land == null || land.IsEitherBannedOrRestricted(UUID)) + selected = false; + else + selected = true; + + } while ( selected == false); + + pos = spawnPoints[index].GetLocation( + telehub.AbsolutePosition, + telehub.GroupRotation + ); + return; + + case "sequence": + + do + { + index = m_scene.SpawnPoint(); + + Vector3 spawnPosition = spawnPoints[index].GetLocation( + telehub.AbsolutePosition, + telehub.GroupRotation + ); + // SpawnPoint sp = spawnPoints[index]; + + ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y); + if (land == null || land.IsEitherBannedOrRestricted(UUID)) + selected = false; + else + selected = true; + + } while (selected == false); + + pos = spawnPoints[index].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); + ; + return; + + default: + return; + } } } } From 30a272ba318c2cacc27f6244dcf829c37a789a7c Mon Sep 17 00:00:00 2001 From: Chris Koeritz Date: Sun, 13 May 2012 16:58:47 -0400 Subject: [PATCH 2/9] Modifications for SMTP in OpenSimulator. Email size limit was fixed (was out of step with documentation at 1024, so boosted to 4096). Added configuration item for maximum email size. Redundant sleep inside email module was fixed (LSL Api was already sleeping). Added sleep time configuration item for snooze between email sending for LSL Api. Added two new configuration items (email_max_size and email_pause_time) into the example OpenSim.ini, plus fixed a spelling error (llimits) and odd tabbing. Signed-off-by: BlueWall --- .../Scripting/EMailModules/EmailModule.cs | 24 ++++------------ .../Shared/Api/Implementation/LSL_Api.cs | 28 ++++++++++++++----- bin/OpenSim.ini.example | 11 ++++++-- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs index 9255791c76..e91e8b9f45 100644 --- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs @@ -64,6 +64,8 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules private TimeSpan m_QueueTimeout = new TimeSpan(2, 0, 0); // 2 hours without llGetNextEmail drops the queue private string m_InterObjectHostname = "lsl.opensim.local"; + private int m_MaxEmailSize = 4096; // largest email allowed by default, as per lsl docs. + // Scenes by Region Handle private Dictionary m_Scenes = new Dictionary(); @@ -127,6 +129,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules SMTP_SERVER_PORT = SMTPConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT); SMTP_SERVER_LOGIN = SMTPConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN); SMTP_SERVER_PASSWORD = SMTPConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD); + m_MaxEmailSize = SMTPConfig.GetInt("email_max_size", m_MaxEmailSize); } catch (Exception e) { @@ -176,18 +179,6 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules get { return true; } } - /// - /// Delay function using thread in seconds - /// - /// - private void DelayInSeconds(int delay) - { - delay = (int)((float)delay * 1000); - if (delay == 0) - return; - System.Threading.Thread.Sleep(delay); - } - private bool IsLocal(UUID objectID) { string unused; @@ -267,10 +258,9 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules m_log.Error("[EMAIL] REGEX Problem in EMail Address: "+address); return; } - //FIXME:Check if subject + body = 4096 Byte - if ((subject.Length + body.Length) > 1024) + if ((subject.Length + body.Length) > m_MaxEmailSize) { - m_log.Error("[EMAIL] subject + body > 1024 Byte"); + m_log.Error("[EMAIL] subject + body larger than limit of " + m_MaxEmailSize + " bytes"); return; } @@ -345,10 +335,6 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules // TODO FIX } } - - //DONE: Message as Second Life style - //20 second delay - AntiSpam System - for now only 10 seconds - DelayInSeconds(10); } /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 5b5cab860c..5bff2e9368 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -106,6 +106,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected IUrlModule m_UrlModule = null; protected Dictionary m_userInfoCache = new Dictionary(); + protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) { @@ -113,6 +114,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host = host; m_item = item; + LoadLimits(); // read script limits from config. + + m_TransferModule = + m_ScriptEngine.World.RequestModuleInterface(); + m_UrlModule = m_ScriptEngine.World.RequestModuleInterface(); + + AsyncCommands = new AsyncCommandManager(ScriptEngine); + } + + /* load configuration items that affect script, object and run-time behavior. */ + private void LoadLimits() + { m_ScriptDelayFactor = m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); m_ScriptDistanceFactor = @@ -125,12 +138,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255); if (m_notecardLineReadCharsMax > 65535) m_notecardLineReadCharsMax = 65535; - - m_TransferModule = - m_ScriptEngine.World.RequestModuleInterface(); - m_UrlModule = m_ScriptEngine.World.RequestModuleInterface(); - - AsyncCommands = new AsyncCommandManager(ScriptEngine); + // load limits for particular subsystems. + IConfig SMTPConfig; + if ((SMTPConfig = m_ScriptEngine.ConfigSource.Configs["SMTP"]) != null) { + // there's an smtp config, so load in the snooze time. + EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); + } } public override Object InitializeLifetimeService() @@ -2877,6 +2890,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public virtual void llSleep(double sec) { +// m_log.Info("llSleep snoozing " + sec + "s."); m_host.AddScriptLPS(1); Thread.Sleep((int)(sec * 1000)); } @@ -3130,7 +3144,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } emailModule.SendEmail(m_host.UUID, address, subject, message); - ScriptSleep(20000); + llSleep(EMAIL_PAUSE_TIME); } public void llGetNextEmail(string address, string subject) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 50366a675d..8e7e45989b 100755 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -273,6 +273,12 @@ ;# {host_domain_header_from} {[Startup]emailmodule:DefaultEmailModule enabled:true} {From address to use in the sent email header?} {} 127.0.0.1 ; host_domain_header_from = "127.0.0.1" + ;# {email_pause_time} {[Startup]emailmodule:DefaultEmailModule enabled:true} {Period in seconds to delay after an email is sent.} {} 20 + ; email_pause_time = 20 + + ;# {email_max_size} {[Startup]emailmodule:DefaultEmailModule enabled:true} {Maximum total size of email in bytes.} {} 4096 + ; email_max_size = 4096 + ;# {SMTP_SERVER_HOSTNAME} {[Startup]emailmodule:DefaultEmailModule enabled:true} {SMTP server name?} {} 127.0.0.1 ; SMTP_SERVER_HOSTNAME = "127.0.0.1" @@ -285,7 +291,6 @@ ;# {SMTP_SERVER_PASSWORD} {[Startup]emailmodule:DefaultEmailModule enabled:true} {SMTP server password} {} ; SMTP_SERVER_PASSWORD = "" - [Network] ;; Configure the remote console user here. This will not actually be used ;; unless you use -console=rest at startup. @@ -677,7 +682,7 @@ ;; Sets the multiplier for the scripting delays ; ScriptDelayFactor = 1.0 - ;; The factor the 10 m distances llimits are multiplied by + ;; The factor the 10 m distances limits are multiplied by ; ScriptDistanceLimitFactor = 1.0 ;; Maximum length of notecard line read @@ -780,7 +785,7 @@ ;; groups service if the service is using these keys ; XmlRpcServiceReadKey = 1234 ; XmlRpcServiceWriteKey = 1234 - + [InterestManagement] ;# {UpdatePrioritizationScheme} {} {Update prioritization scheme?} {BestAvatarResponsiveness Time Distance SimpleAngularDistance FrontBack} BestAvatarResponsiveness ;; This section controls how state updates are prioritized for each client From 847127f83c4a6fbfb9be0ecef3904393e6968908 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Mon, 14 May 2012 00:15:56 -0400 Subject: [PATCH 3/9] Oops - missed the config changes --- bin/OpenSim.ini.example | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 8e7e45989b..9b88816893 100755 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -241,6 +241,14 @@ ;; server to send mail through. ; emailmodule = DefaultEmailModule + ;# {SpawnPointRouting} {} {Set routing method for Telehub Spawnpoints} {closest random sequential} closest + ;; SpawnPointRouting adjusts the landing for incoming avatars. + ;; "closest" will place the avatar at the SpawnPoint located in the closest + ;; available spot to the destination (typically map click/landmark). + ;; "random" will place the avatar on a randomly selected spawnpoint; + ;; "sequential" will place the avatar on the next sequential SpawnPoint + ; SpawnPointRouting = closest + [Estates] ; If these values are commented out then the user will be asked for estate details when required (this is the normal case). ; If these values are uncommented then they will be used to create a default estate as necessary. From fad557485c78e15380ec35c0dbcf8556a96d29f7 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 14 May 2012 18:06:48 +0100 Subject: [PATCH 4/9] Add more region information to some teleport related logging --- .../EntityTransfer/EntityTransferModule.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index cd588e5d86..9766a25da4 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -53,7 +53,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer public const int DefaultMaxTransferDistance = 4095; public const bool EnableWaitForCallbackFromTeleportDestDefault = true; - /// /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer. /// @@ -531,8 +530,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // Region doesn't take it m_log.WarnFormat( - "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Returning avatar to source region.", - sp.Name, finalDestination.RegionName); + "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Returning avatar to source region.", + sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); Fail(sp, finalDestination, logout); return; @@ -564,8 +563,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (EnableWaitForCallbackFromTeleportDest && !WaitForCallback(sp.UUID)) { m_log.WarnFormat( - "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} failed due to no callback from destination region. Returning avatar to source region.", - sp.Name, finalDestination.RegionName); + "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", + sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); Fail(sp, finalDestination, logout); return; @@ -661,8 +660,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) { agent.CallbackURI = region.ServerURI + "agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/"; - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Set callback URL to {0}", agent.CallbackURI); + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: Set release callback URL to {0} in {1}", + agent.CallbackURI, region.RegionName); } protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout) @@ -2014,4 +2015,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #endregion } -} +} \ No newline at end of file From c2aa3b90d9d367bcaeba93352ef6b0f513e663f7 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 14 May 2012 18:36:26 +0100 Subject: [PATCH 5/9] Set the agent in transit teleport flag at the first available opportunity (i.e. when IsInTransit() was being checked) to close down a race condition. On EntityTransferModule.DoTeleport() there was an IsInTransit() check to prevent multiple simultaneous teleport attempts. However, the SetInTransit() was only performed later on, which left a window in which multiple threads could pass the IsInTransit() check. This has been seen in the field and the results aren't pretty. This commit effectively combines the IsInTransit() and SetInTransit() checks so there is no such window. More failure cases are made to to call ResetInTransit() to adjust to this move. --- .../EntityTransfer/EntityTransferModule.cs | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 9766a25da4..d0aead5a7c 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -210,6 +210,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, e.Message, e.StackTrace); + // Make sure that we clear the in-transit flag so that future teleport attempts don't always fail. + ResetFromTransit(sp.UUID); + sp.ControllingClient.SendTeleportFailed("Internal error"); } } @@ -384,7 +387,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } - if (IsInTransit(sp.UUID)) // Avie is already on the way. Caller shouldn't do this. + if (!SetInTransit(sp.UUID)) // Avie is already on the way. Caller shouldn't do this. { m_log.DebugFormat( "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", @@ -432,8 +435,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) { sp.ControllingClient.SendTeleportFailed("Teleport failed: " + reason); + ResetFromTransit(sp.UUID); + return; } + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); sp.ControllingClient.SendTeleportStart(teleportFlags); @@ -473,13 +479,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer bool logout = false; if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) { - sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", - reason)); + sp.ControllingClient.SendTeleportFailed( + String.Format("Teleport refused: {0}", reason)); + ResetFromTransit(sp.UUID); + return; } // OK, it got this agent. Let's close some child agents sp.CloseChildAgents(newRegionX, newRegionY); + IClientIPEndpoint ipepClient; if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) { @@ -516,8 +525,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); } - SetInTransit(sp.UUID); - // Let's send a full update of the agent. This is a synchronous call. AgentData agent = new AgentData(); sp.CopyTo(agent); @@ -1956,25 +1963,43 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return count > 0; } - protected void SetInTransit(UUID id) + /// + /// Set that an agent is in the process of being teleported. + /// + /// The ID of the agent being teleported + /// true if the agent was not already in transit, false if it was + protected bool SetInTransit(UUID id) { lock (m_agentsInTransit) { if (!m_agentsInTransit.Contains(id)) + { m_agentsInTransit.Add(id); - } - } - - protected bool IsInTransit(UUID id) - { - lock (m_agentsInTransit) - { - if (m_agentsInTransit.Contains(id)) return true; + } } + return false; } + /// + /// Show whether the given agent is being teleported. + /// + /// true if the agent is in the process of being teleported, false otherwise. + /// The agent ID + protected bool IsInTransit(UUID id) + { + lock (m_agentsInTransit) + return m_agentsInTransit.Contains(id); + } + + /// + /// Set that an agent is no longer being teleported. + /// + /// + /// + /// true if the agent was flagged as being teleported when this method was called, false otherwise + /// protected bool ResetFromTransit(UUID id) { lock (m_agentsInTransit) @@ -1985,6 +2010,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return true; } } + return false; } From deeac6931242f1bbb05f0ec36c31a147b32d4b26 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 14 May 2012 18:48:40 +0100 Subject: [PATCH 6/9] minor: comment out individual attachment transfer log messages for now --- OpenSim/Region/Framework/Scenes/Scene.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2a2830f47d..2bf3638f6c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2576,10 +2576,10 @@ namespace OpenSim.Region.Framework.Scenes { SceneObjectGroup grp = sceneObject; - m_log.DebugFormat( - "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID); - m_log.DebugFormat( - "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); +// m_log.DebugFormat( +// "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID); +// m_log.DebugFormat( +// "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); RootPrim.RemFlag(PrimFlags.TemporaryOnRez); From af6c85308adced4ac4a51bf14bd2beb7f22c6555 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 14 May 2012 18:57:02 +0100 Subject: [PATCH 7/9] minor: add explanative comment to 'missing baked texture' logging commonly seen on inter-simulator teleports where avatar baked textures are not available from the asset service. --- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 0ed10d2864..705233c2d7 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -371,11 +371,21 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory if (missingTexturesOnly) { if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) + { continue; + } else + { + // On inter-simulator teleports, this occurs if baked textures are not being stored by the + // grid asset service (which means that they are not available to the new region and so have + // to be re-requested from the client). + // + // The only available core OpenSimulator behaviour right now + // is not to store these textures, temporarily or otherwise. m_log.DebugFormat( "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", face.TextureID, idx, sp.Name); + } } else { From d7fd9b159a7af813cfd6901a65e0ed43a6e1593d Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 14 May 2012 19:36:26 +0100 Subject: [PATCH 8/9] set executable bit for Ionic.Zip.dll for running OpenSimulator under cygwin --- bin/Ionic.Zip.dll | Bin 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bin/Ionic.Zip.dll diff --git a/bin/Ionic.Zip.dll b/bin/Ionic.Zip.dll old mode 100644 new mode 100755 From 52a32878a9573681e3b56d0151c4a0903719eadf Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Thu, 3 May 2012 19:38:35 +0300 Subject: [PATCH 9/9] Save the Telehub and its Spawn Points in the OAR --- OpenSim/Framework/RegionSettings.cs | 29 ++++++++++++++- .../External/RegionSettingsSerializer.cs | 37 ++++++++++++++++++- .../Tests/RegionSettingsSerializerTests.cs | 8 ++++ .../World/Archiver/ArchiveReadRequest.cs | 25 ++++++++++++- .../ArchiveWriteRequestPreparation.cs | 2 +- .../World/Archiver/Tests/ArchiverTests.cs | 4 ++ 6 files changed, 100 insertions(+), 5 deletions(-) diff --git a/OpenSim/Framework/RegionSettings.cs b/OpenSim/Framework/RegionSettings.cs index 4ce3392057..47dbcecaeb 100644 --- a/OpenSim/Framework/RegionSettings.cs +++ b/OpenSim/Framework/RegionSettings.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using System.IO; using OpenMetaverse; +using System.Runtime.Serialization; namespace OpenSim.Framework { @@ -71,6 +72,32 @@ namespace OpenSim.Framework return pos + offset; } + + /// + /// Returns a string representation of this SpawnPoint. + /// + /// + public override string ToString() + { + return string.Format("{0},{1},{2}", Yaw, Pitch, Distance); + } + + /// + /// Generate a SpawnPoint from a string + /// + /// + public static SpawnPoint Parse(string str) + { + string[] parts = str.Split(','); + if (parts.Length != 3) + throw new ArgumentException("Invalid string: " + str); + + SpawnPoint sp = new SpawnPoint(); + sp.Yaw = float.Parse(parts[0]); + sp.Pitch = float.Parse(parts[1]); + sp.Distance = float.Parse(parts[2]); + return sp; + } } public class RegionSettings @@ -456,7 +483,7 @@ namespace OpenSim.Framework } // Connected Telehub object - private UUID m_TelehubObject; + private UUID m_TelehubObject = UUID.Zero; public UUID TelehubObject { get diff --git a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs index 931898ce10..f18435d308 100644 --- a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs +++ b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs @@ -30,6 +30,8 @@ using System.Text; using System.Xml; using OpenMetaverse; using OpenSim.Framework; +using log4net; +using System.Reflection; namespace OpenSim.Framework.Serialization.External { @@ -187,7 +189,29 @@ namespace OpenSim.Framework.Serialization.External break; } } - + + xtr.ReadEndElement(); + + if (xtr.IsStartElement("Telehub")) + { + xtr.ReadStartElement("Telehub"); + + while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) + { + switch (xtr.Name) + { + case "TelehubObject": + settings.TelehubObject = UUID.Parse(xtr.ReadElementContentAsString()); + break; + case "SpawnPoint": + string str = xtr.ReadElementContentAsString(); + SpawnPoint sp = SpawnPoint.Parse(str); + settings.AddSpawnPoint(sp); + break; + } + } + } + xtr.Close(); sr.Close(); @@ -243,7 +267,16 @@ namespace OpenSim.Framework.Serialization.External 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(); + + xtw.WriteStartElement("Telehub"); + if (settings.TelehubObject != UUID.Zero) + { + xtw.WriteElementString("TelehubObject", settings.TelehubObject.ToString()); + foreach (SpawnPoint sp in settings.SpawnPoints()) + xtw.WriteElementString("SpawnPoint", sp.ToString()); + } + xtw.WriteEndElement(); xtw.WriteEndElement(); diff --git a/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs b/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs index a61e4af65d..09b6f6ddad 100644 --- a/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs +++ b/OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs @@ -78,6 +78,10 @@ namespace OpenSim.Framework.Serialization.Tests true 12 + + 00000000-0000-0000-0000-111111111111 + 1,-2,0.33 + "; private RegionSettings m_rs; @@ -116,6 +120,8 @@ namespace OpenSim.Framework.Serialization.Tests m_rs.TerrainTexture4 = UUID.Parse("00000000-0000-0000-0000-000000000080"); m_rs.UseEstateSun = true; m_rs.WaterHeight = 23; + m_rs.TelehubObject = UUID.Parse("00000000-0000-0000-0000-111111111111"); + m_rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33")); } [Test] @@ -129,6 +135,8 @@ namespace OpenSim.Framework.Serialization.Tests Assert.That(deserRs.TerrainTexture2, Is.EqualTo(m_rs.TerrainTexture2)); Assert.That(deserRs.DisablePhysics, Is.EqualTo(m_rs.DisablePhysics)); Assert.That(deserRs.TerrainLowerLimit, Is.EqualTo(m_rs.TerrainLowerLimit)); + Assert.That(deserRs.TelehubObject, Is.EqualTo(m_rs.TelehubObject)); + Assert.That(deserRs.SpawnPoints()[0].ToString(), Is.EqualTo(m_rs.SpawnPoints()[0].ToString())); } } } diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index a6dbaba7d7..bf0ff7516b 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -245,6 +245,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Reload serialized prims m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); + UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject; + IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface(); int sceneObjectsLoadedCount = 0; @@ -266,11 +268,21 @@ namespace OpenSim.Region.CoreModules.World.Archiver SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); + bool isTelehub = (sceneObject.UUID == oldTelehubUUID); + // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned // on the same region server and multiple examples a single object archive to be imported // to the same scene (when this is possible). sceneObject.ResetIDs(); + if (isTelehub) + { + // Change the Telehub Object to the new UUID + m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; + m_scene.RegionInfo.RegionSettings.Save(); + oldTelehubUUID = UUID.Zero; + } + // Try to retain the original creator/owner/lastowner if their uuid is present on this grid // or creator data is present. Otherwise, use the estate owner instead. foreach (SceneObjectPart part in sceneObject.Parts) @@ -329,7 +341,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount; if (ignoredObjects > 0) - m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects); + m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects); + + if (oldTelehubUUID != UUID.Zero) + { + m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); + m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; + m_scene.RegionInfo.RegionSettings.ClearSpawnPoints(); + } } /// @@ -505,6 +524,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver currentRegionSettings.TerrainTexture4 = loadedRegionSettings.TerrainTexture4; currentRegionSettings.UseEstateSun = loadedRegionSettings.UseEstateSun; currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight; + currentRegionSettings.TelehubObject = loadedRegionSettings.TelehubObject; + currentRegionSettings.ClearSpawnPoints(); + foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints()) + currentRegionSettings.AddSpawnPoint(sp); currentRegionSettings.Save(); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index eabe46e936..5679ad5dcb 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -328,7 +328,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// public string CreateControlFile(Dictionary options) { - int majorVersion = MAX_MAJOR_VERSION, minorVersion = 7; + int majorVersion = MAX_MAJOR_VERSION, minorVersion = 8; // // if (options.ContainsKey("version")) // { diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 053c6f59d4..394ca27123 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -534,6 +534,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests rs.TerrainTexture4 = UUID.Parse("00000000-0000-0000-0000-000000000080"); rs.UseEstateSun = true; rs.WaterHeight = 23; + rs.TelehubObject = UUID.Parse("00000000-0000-0000-0000-111111111111"); + rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33")); tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs)); @@ -580,6 +582,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(loadedRs.TerrainTexture4, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000080"))); Assert.That(loadedRs.UseEstateSun, Is.True); Assert.That(loadedRs.WaterHeight, Is.EqualTo(23)); + Assert.AreEqual(UUID.Zero, loadedRs.TelehubObject); // because no object was found with the original UUID + Assert.AreEqual(0, loadedRs.SpawnPoints().Count); } ///