diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 507 |
1 files changed, 297 insertions, 210 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 8d112db..c8e7156 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -80,6 +80,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
80 | public SynchronizeSceneHandler SynchronizeScene; | 80 | public SynchronizeSceneHandler SynchronizeScene; |
81 | 81 | ||
82 | /// <summary> | 82 | /// <summary> |
83 | /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. | ||
84 | /// </summary> | ||
85 | private object m_removeClientLock = new object(); | ||
86 | |||
87 | /// <summary> | ||
83 | /// Statistical information for this scene. | 88 | /// Statistical information for this scene. |
84 | /// </summary> | 89 | /// </summary> |
85 | public SimStatsReporter StatsReporter { get; private set; } | 90 | public SimStatsReporter StatsReporter { get; private set; } |
@@ -308,6 +313,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
308 | } | 313 | } |
309 | private volatile bool m_shuttingDown; | 314 | private volatile bool m_shuttingDown; |
310 | 315 | ||
316 | /// <summary> | ||
317 | /// Is the scene active? | ||
318 | /// </summary> | ||
319 | /// <remarks> | ||
320 | /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if | ||
321 | /// the scene is not active. | ||
322 | /// </remarks> | ||
323 | public bool Active | ||
324 | { | ||
325 | get { return m_active; } | ||
326 | set | ||
327 | { | ||
328 | if (value) | ||
329 | { | ||
330 | if (!m_active) | ||
331 | Start(); | ||
332 | } | ||
333 | else | ||
334 | { | ||
335 | m_active = false; | ||
336 | } | ||
337 | } | ||
338 | } | ||
339 | private volatile bool m_active; | ||
340 | |||
311 | // private int m_lastUpdate; | 341 | // private int m_lastUpdate; |
312 | private bool m_firstHeartbeat = true; | 342 | private bool m_firstHeartbeat = true; |
313 | 343 | ||
@@ -1187,6 +1217,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1187 | 1217 | ||
1188 | public void SetSceneCoreDebug(Dictionary<string, string> options) | 1218 | public void SetSceneCoreDebug(Dictionary<string, string> options) |
1189 | { | 1219 | { |
1220 | if (options.ContainsKey("active")) | ||
1221 | { | ||
1222 | bool active; | ||
1223 | |||
1224 | if (bool.TryParse(options["active"], out active)) | ||
1225 | Active = active; | ||
1226 | } | ||
1227 | |||
1190 | if (options.ContainsKey("scripting")) | 1228 | if (options.ContainsKey("scripting")) |
1191 | { | 1229 | { |
1192 | bool enableScripts = true; | 1230 | bool enableScripts = true; |
@@ -1326,6 +1364,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1326 | /// </summary> | 1364 | /// </summary> |
1327 | public void Start() | 1365 | public void Start() |
1328 | { | 1366 | { |
1367 | m_active = true; | ||
1368 | |||
1329 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); | 1369 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); |
1330 | 1370 | ||
1331 | //m_heartbeatTimer.Enabled = true; | 1371 | //m_heartbeatTimer.Enabled = true; |
@@ -1382,7 +1422,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1382 | #region Update Methods | 1422 | #region Update Methods |
1383 | 1423 | ||
1384 | /// <summary> | 1424 | /// <summary> |
1385 | /// Performs per-frame updates regularly | 1425 | /// Activate the various loops necessary to continually update the scene. |
1386 | /// </summary> | 1426 | /// </summary> |
1387 | private void Heartbeat() | 1427 | private void Heartbeat() |
1388 | { | 1428 | { |
@@ -1439,7 +1479,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1439 | List<Vector3> coarseLocations; | 1479 | List<Vector3> coarseLocations; |
1440 | List<UUID> avatarUUIDs; | 1480 | List<UUID> avatarUUIDs; |
1441 | 1481 | ||
1442 | while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) | 1482 | while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) |
1443 | { | 1483 | { |
1444 | runtc = Util.EnvironmentTickCount(); | 1484 | runtc = Util.EnvironmentTickCount(); |
1445 | ++MaintenanceRun; | 1485 | ++MaintenanceRun; |
@@ -1501,7 +1541,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1501 | int sleepMS; | 1541 | int sleepMS; |
1502 | int framestart; | 1542 | int framestart; |
1503 | 1543 | ||
1504 | while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) | 1544 | while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) |
1505 | { | 1545 | { |
1506 | framestart = Util.EnvironmentTickCount(); | 1546 | framestart = Util.EnvironmentTickCount(); |
1507 | ++Frame; | 1547 | ++Frame; |
@@ -2218,10 +2258,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2218 | public bool AddRestoredSceneObject( | 2258 | public bool AddRestoredSceneObject( |
2219 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 2259 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
2220 | { | 2260 | { |
2221 | bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); | 2261 | if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) |
2222 | if (result) | 2262 | { |
2223 | sceneObject.IsDeleted = false; | 2263 | sceneObject.IsDeleted = false; |
2224 | return result; | 2264 | EventManager.TriggerObjectAddedToScene(sceneObject); |
2265 | return true; | ||
2266 | } | ||
2267 | |||
2268 | return false; | ||
2225 | } | 2269 | } |
2226 | 2270 | ||
2227 | /// <summary> | 2271 | /// <summary> |
@@ -2862,77 +2906,89 @@ namespace OpenSim.Region.Framework.Scenes | |||
2862 | 2906 | ||
2863 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) | 2907 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) |
2864 | { | 2908 | { |
2909 | ScenePresence sp; | ||
2910 | bool vialogin; | ||
2911 | |||
2865 | // Validation occurs in LLUDPServer | 2912 | // Validation occurs in LLUDPServer |
2913 | // | ||
2914 | // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with | ||
2915 | // each other. In practice, this does not currently occur in the code. | ||
2866 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); | 2916 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); |
2867 | 2917 | ||
2868 | bool vialogin | 2918 | // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection |
2869 | = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 | 2919 | // and a simultaneous one that removes it (as can happen if the client is closed at a particular point |
2870 | || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; | 2920 | // whilst connecting). |
2871 | 2921 | // | |
2872 | CheckHeartbeat(); | 2922 | // It would be easier to lock across all NewUserConnection(), AddNewClient() and |
2873 | 2923 | // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service | |
2874 | ScenePresence sp = GetScenePresence(client.AgentId); | 2924 | // response in some module listening to AddNewClient()) from holding up unrelated agent calls. |
2875 | 2925 | // | |
2876 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this | 2926 | // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all |
2877 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause | 2927 | // AddNewClient() operations (though not other ops). |
2878 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already | 2928 | // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. |
2879 | // connected. | 2929 | lock (aCircuit) |
2880 | if (sp == null) | 2930 | { |
2881 | { | 2931 | vialogin |
2882 | m_log.DebugFormat( | 2932 | = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 |
2883 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", | 2933 | || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; |
2884 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); | 2934 | |
2885 | 2935 | CheckHeartbeat(); | |
2886 | m_clientManager.Add(client); | 2936 | |
2887 | SubscribeToClientEvents(client); | 2937 | sp = GetScenePresence(client.AgentId); |
2888 | |||
2889 | sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); | ||
2890 | m_eventManager.TriggerOnNewPresence(sp); | ||
2891 | |||
2892 | sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; | ||
2893 | 2938 | ||
2894 | // The first agent upon login is a root agent by design. | 2939 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this |
2895 | // For this agent we will have to rez the attachments. | 2940 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause |
2896 | // All other AddNewClient calls find aCircuit.child to be true. | 2941 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already |
2897 | if (aCircuit.child == false) | 2942 | // connected. |
2943 | if (sp == null) | ||
2898 | { | 2944 | { |
2899 | // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to | 2945 | m_log.DebugFormat( |
2900 | // start the scripts again (since this is done in RezAttachments()). | 2946 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", |
2901 | // XXX: This is convoluted. | 2947 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); |
2902 | sp.IsChildAgent = false; | 2948 | |
2903 | 2949 | m_clientManager.Add(client); | |
2904 | if (AttachmentsModule != null) | 2950 | SubscribeToClientEvents(client); |
2905 | Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); | 2951 | |
2952 | sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); | ||
2953 | m_eventManager.TriggerOnNewPresence(sp); | ||
2954 | |||
2955 | sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; | ||
2956 | |||
2957 | // The first agent upon login is a root agent by design. | ||
2958 | // For this agent we will have to rez the attachments. | ||
2959 | // All other AddNewClient calls find aCircuit.child to be true. | ||
2960 | if (aCircuit.child == false) | ||
2961 | { | ||
2962 | // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to | ||
2963 | // start the scripts again (since this is done in RezAttachments()). | ||
2964 | // XXX: This is convoluted. | ||
2965 | sp.IsChildAgent = false; | ||
2966 | |||
2967 | if (AttachmentsModule != null) | ||
2968 | Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); | ||
2969 | } | ||
2906 | } | 2970 | } |
2907 | } | 2971 | else |
2908 | else | 2972 | { |
2909 | { | 2973 | m_log.WarnFormat( |
2910 | m_log.WarnFormat( | 2974 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", |
2911 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", | 2975 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); |
2912 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); | 2976 | } |
2913 | } | 2977 | |
2978 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | ||
2979 | // client is for a root or child agent. | ||
2980 | client.SceneAgent = sp; | ||
2914 | 2981 | ||
2915 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | 2982 | // Cache the user's name |
2916 | // client is for a root or child agent. | 2983 | CacheUserName(sp, aCircuit); |
2917 | client.SceneAgent = sp; | 2984 | |
2985 | EventManager.TriggerOnNewClient(client); | ||
2986 | if (vialogin) | ||
2987 | EventManager.TriggerOnClientLogin(client); | ||
2988 | } | ||
2918 | 2989 | ||
2919 | m_LastLogin = Util.EnvironmentTickCount(); | 2990 | m_LastLogin = Util.EnvironmentTickCount(); |
2920 | 2991 | ||
2921 | // Cache the user's name | ||
2922 | CacheUserName(sp, aCircuit); | ||
2923 | |||
2924 | EventManager.TriggerOnNewClient(client); | ||
2925 | if (vialogin) | ||
2926 | { | ||
2927 | EventManager.TriggerOnClientLogin(client); | ||
2928 | // Send initial parcel data | ||
2929 | /* this is done on TriggerOnNewClient by landmanegement respective event handler | ||
2930 | Vector3 pos = sp.AbsolutePosition; | ||
2931 | ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y); | ||
2932 | land.SendLandUpdateToClient(client); | ||
2933 | */ | ||
2934 | } | ||
2935 | |||
2936 | return sp; | 2992 | return sp; |
2937 | } | 2993 | } |
2938 | 2994 | ||
@@ -3472,110 +3528,130 @@ namespace OpenSim.Region.Framework.Scenes | |||
3472 | { | 3528 | { |
3473 | // CheckHeartbeat(); | 3529 | // CheckHeartbeat(); |
3474 | bool isChildAgent = false; | 3530 | bool isChildAgent = false; |
3475 | ScenePresence avatar = GetScenePresence(agentID); | 3531 | AgentCircuitData acd; |
3476 | |||
3477 | if (avatar == null) | ||
3478 | { | ||
3479 | m_log.WarnFormat( | ||
3480 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); | ||
3481 | 3532 | ||
3482 | return; | 3533 | lock (m_removeClientLock) |
3483 | } | ||
3484 | |||
3485 | try | ||
3486 | { | 3534 | { |
3487 | isChildAgent = avatar.IsChildAgent; | 3535 | acd = m_authenticateHandler.GetAgentCircuitData(agentID); |
3488 | 3536 | ||
3489 | m_log.DebugFormat( | 3537 | if (acd == null) |
3490 | "[SCENE]: Removing {0} agent {1} {2} from {3}", | ||
3491 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); | ||
3492 | |||
3493 | // Don't do this to root agents, it's not nice for the viewer | ||
3494 | if (closeChildAgents && isChildAgent) | ||
3495 | { | 3538 | { |
3496 | // Tell a single agent to disconnect from the region. | 3539 | m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); |
3497 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | 3540 | return; |
3498 | if (eq != null) | ||
3499 | { | ||
3500 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); | ||
3501 | } | ||
3502 | else | ||
3503 | { | ||
3504 | avatar.ControllingClient.SendShutdownConnectionNotice(); | ||
3505 | } | ||
3506 | } | 3541 | } |
3507 | 3542 | else | |
3508 | // Only applies to root agents. | ||
3509 | if (avatar.ParentID != 0) | ||
3510 | { | 3543 | { |
3511 | avatar.StandUp(); | 3544 | // We remove the acd up here to avoid later raec conditions if two RemoveClient() calls occurred |
3545 | // simultaneously. | ||
3546 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); | ||
3512 | } | 3547 | } |
3548 | } | ||
3513 | 3549 | ||
3514 | m_sceneGraph.removeUserCount(!isChildAgent); | 3550 | lock (acd) |
3515 | 3551 | { | |
3516 | // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop | 3552 | ScenePresence avatar = GetScenePresence(agentID); |
3517 | // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI | 3553 | |
3518 | if (closeChildAgents && CapsModule != null) | 3554 | if (avatar == null) |
3519 | CapsModule.RemoveCaps(agentID); | ||
3520 | |||
3521 | // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | ||
3522 | // this method is doing is HORRIBLE!!! | ||
3523 | avatar.Scene.NeedSceneCacheClear(avatar.UUID); | ||
3524 | |||
3525 | if (closeChildAgents && !isChildAgent) | ||
3526 | { | 3555 | { |
3527 | List<ulong> regions = avatar.KnownRegionHandles; | 3556 | m_log.WarnFormat( |
3528 | regions.Remove(RegionInfo.RegionHandle); | 3557 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); |
3529 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | 3558 | |
3559 | return; | ||
3530 | } | 3560 | } |
3531 | 3561 | ||
3532 | m_eventManager.TriggerClientClosed(agentID, this); | 3562 | try |
3533 | m_eventManager.TriggerOnRemovePresence(agentID); | ||
3534 | |||
3535 | if (!isChildAgent) | ||
3536 | { | 3563 | { |
3537 | if (AttachmentsModule != null) | 3564 | isChildAgent = avatar.IsChildAgent; |
3565 | |||
3566 | m_log.DebugFormat( | ||
3567 | "[SCENE]: Removing {0} agent {1} {2} from {3}", | ||
3568 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); | ||
3569 | |||
3570 | // Don't do this to root agents, it's not nice for the viewer | ||
3571 | if (closeChildAgents && isChildAgent) | ||
3538 | { | 3572 | { |
3539 | AttachmentsModule.DeRezAttachments(avatar); | 3573 | // Tell a single agent to disconnect from the region. |
3574 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | ||
3575 | if (eq != null) | ||
3576 | { | ||
3577 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); | ||
3578 | } | ||
3579 | else | ||
3580 | { | ||
3581 | avatar.ControllingClient.SendShutdownConnectionNotice(); | ||
3582 | } | ||
3540 | } | 3583 | } |
3541 | 3584 | ||
3542 | ForEachClient( | 3585 | // Only applies to root agents. |
3543 | delegate(IClientAPI client) | 3586 | if (avatar.ParentID != 0) |
3587 | { | ||
3588 | avatar.StandUp(); | ||
3589 | } | ||
3590 | |||
3591 | m_sceneGraph.removeUserCount(!isChildAgent); | ||
3592 | |||
3593 | // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop | ||
3594 | // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI | ||
3595 | if (closeChildAgents && CapsModule != null) | ||
3596 | CapsModule.RemoveCaps(agentID); | ||
3597 | |||
3598 | // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | ||
3599 | // this method is doing is HORRIBLE!!! | ||
3600 | avatar.Scene.NeedSceneCacheClear(avatar.UUID); | ||
3601 | |||
3602 | if (closeChildAgents && !isChildAgent) | ||
3603 | { | ||
3604 | List<ulong> regions = avatar.KnownRegionHandles; | ||
3605 | regions.Remove(RegionInfo.RegionHandle); | ||
3606 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | ||
3607 | } | ||
3608 | |||
3609 | m_eventManager.TriggerClientClosed(agentID, this); | ||
3610 | m_eventManager.TriggerOnRemovePresence(agentID); | ||
3611 | |||
3612 | if (!isChildAgent) | ||
3613 | { | ||
3614 | if (AttachmentsModule != null) | ||
3544 | { | 3615 | { |
3545 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway | 3616 | AttachmentsModule.DeRezAttachments(avatar); |
3546 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } | 3617 | } |
3547 | catch (NullReferenceException) { } | ||
3548 | }); | ||
3549 | } | ||
3550 | |||
3551 | // It's possible for child agents to have transactions if changes are being made cross-border. | ||
3552 | if (AgentTransactionsModule != null) | ||
3553 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); | ||
3554 | 3618 | ||
3555 | m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); | 3619 | ForEachClient( |
3556 | m_log.Debug("[Scene] The avatar has left the building"); | 3620 | delegate(IClientAPI client) |
3557 | } | 3621 | { |
3558 | catch (Exception e) | 3622 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway |
3559 | { | 3623 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } |
3560 | m_log.Error( | 3624 | catch (NullReferenceException) { } |
3561 | string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); | 3625 | }); |
3562 | } | 3626 | } |
3563 | finally | ||
3564 | { | ||
3565 | try | ||
3566 | { | ||
3567 | // Always clean these structures up so that any failure above doesn't cause them to remain in the | ||
3568 | // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering | ||
3569 | // the same cleanup exception continually. | ||
3570 | m_sceneGraph.RemoveScenePresence(agentID); | ||
3571 | m_clientManager.Remove(agentID); | ||
3572 | 3627 | ||
3573 | avatar.Close(); | 3628 | // It's possible for child agents to have transactions if changes are being made cross-border. |
3629 | if (AgentTransactionsModule != null) | ||
3630 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); | ||
3631 | m_log.Debug("[Scene] The avatar has left the building"); | ||
3574 | } | 3632 | } |
3575 | catch (Exception e) | 3633 | catch (Exception e) |
3576 | { | 3634 | { |
3577 | m_log.Error( | 3635 | m_log.Error( |
3578 | string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); | 3636 | string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); |
3637 | } | ||
3638 | finally | ||
3639 | { | ||
3640 | try | ||
3641 | { | ||
3642 | // Always clean these structures up so that any failure above doesn't cause them to remain in the | ||
3643 | // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering | ||
3644 | // the same cleanup exception continually. | ||
3645 | m_sceneGraph.RemoveScenePresence(agentID); | ||
3646 | m_clientManager.Remove(agentID); | ||
3647 | |||
3648 | avatar.Close(); | ||
3649 | } | ||
3650 | catch (Exception e) | ||
3651 | { | ||
3652 | m_log.Error( | ||
3653 | string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); | ||
3654 | } | ||
3579 | } | 3655 | } |
3580 | } | 3656 | } |
3581 | 3657 | ||
@@ -3634,11 +3710,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3634 | 3710 | ||
3635 | /// <summary> | 3711 | /// <summary> |
3636 | /// Do the work necessary to initiate a new user connection for a particular scene. | 3712 | /// Do the work necessary to initiate a new user connection for a particular scene. |
3637 | /// At the moment, this consists of setting up the caps infrastructure | ||
3638 | /// The return bool should allow for connections to be refused, but as not all calling paths | ||
3639 | /// take proper notice of it let, we allowed banned users in still. | ||
3640 | /// </summary> | 3713 | /// </summary> |
3641 | /// <param name="agent">CircuitData of the agent who is connecting</param> | 3714 | /// <param name="agent">CircuitData of the agent who is connecting</param> |
3715 | /// <param name="teleportFlags"></param> | ||
3642 | /// <param name="reason">Outputs the reason for the false response on this string</param> | 3716 | /// <param name="reason">Outputs the reason for the false response on this string</param> |
3643 | /// <returns>True if the region accepts this agent. False if it does not. False will | 3717 | /// <returns>True if the region accepts this agent. False if it does not. False will |
3644 | /// also return a reason.</returns> | 3718 | /// also return a reason.</returns> |
@@ -3649,10 +3723,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
3649 | 3723 | ||
3650 | /// <summary> | 3724 | /// <summary> |
3651 | /// Do the work necessary to initiate a new user connection for a particular scene. | 3725 | /// Do the work necessary to initiate a new user connection for a particular scene. |
3652 | /// At the moment, this consists of setting up the caps infrastructure | 3726 | /// </summary> |
3727 | /// <remarks> | ||
3728 | /// The return bool should allow for connections to be refused, but as not all calling paths | ||
3729 | /// take proper notice of it yet, we still allowed banned users in. | ||
3730 | /// | ||
3731 | /// At the moment this method consists of setting up the caps infrastructure | ||
3653 | /// The return bool should allow for connections to be refused, but as not all calling paths | 3732 | /// The return bool should allow for connections to be refused, but as not all calling paths |
3654 | /// take proper notice of it let, we allowed banned users in still. | 3733 | /// take proper notice of it let, we allowed banned users in still. |
3655 | /// </summary> | 3734 | /// |
3735 | /// This method is called by the login service (in the case of login) or another simulator (in the case of region | ||
3736 | /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection | ||
3737 | /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of | ||
3738 | /// the LLUDP stack). | ||
3739 | /// </remarks> | ||
3656 | /// <param name="agent">CircuitData of the agent who is connecting</param> | 3740 | /// <param name="agent">CircuitData of the agent who is connecting</param> |
3657 | /// <param name="reason">Outputs the reason for the false response on this string</param> | 3741 | /// <param name="reason">Outputs the reason for the false response on this string</param> |
3658 | /// <param name="requirePresenceLookup">True for normal presence. False for NPC | 3742 | /// <param name="requirePresenceLookup">True for normal presence. False for NPC |
@@ -3755,79 +3839,82 @@ namespace OpenSim.Region.Framework.Scenes | |||
3755 | sp = null; | 3839 | sp = null; |
3756 | } | 3840 | } |
3757 | 3841 | ||
3758 | 3842 | lock (agent) | |
3759 | //On login test land permisions | ||
3760 | if (vialogin) | ||
3761 | { | 3843 | { |
3762 | IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); | 3844 | //On login test land permisions |
3763 | if (cache != null) | 3845 | if (vialogin) |
3764 | cache.Remove(agent.firstname + " " + agent.lastname); | ||
3765 | if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) | ||
3766 | { | 3846 | { |
3767 | m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); | 3847 | IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); |
3768 | return false; | 3848 | if (cache != null) |
3849 | cache.Remove(agent.firstname + " " + agent.lastname); | ||
3850 | if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) | ||
3851 | { | ||
3852 | m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); | ||
3853 | return false; | ||
3854 | } | ||
3769 | } | 3855 | } |
3770 | } | ||
3771 | 3856 | ||
3772 | if (sp == null) // We don't have an [child] agent here already | 3857 | if (sp == null) // We don't have an [child] agent here already |
3773 | { | ||
3774 | if (requirePresenceLookup) | ||
3775 | { | 3858 | { |
3776 | try | 3859 | if (requirePresenceLookup) |
3777 | { | 3860 | { |
3778 | if (!VerifyUserPresence(agent, out reason)) | 3861 | try |
3862 | { | ||
3863 | if (!VerifyUserPresence(agent, out reason)) | ||
3864 | return false; | ||
3865 | } catch (Exception e) | ||
3866 | { | ||
3867 | m_log.ErrorFormat( | ||
3868 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); | ||
3779 | return false; | 3869 | return false; |
3780 | } catch (Exception e) | 3870 | } |
3871 | } | ||
3872 | |||
3873 | try | ||
3874 | { | ||
3875 | // Always check estate if this is a login. Always | ||
3876 | // check if banned regions are to be blacked out. | ||
3877 | if (vialogin || (!m_seeIntoBannedRegion)) | ||
3878 | { | ||
3879 | if (!AuthorizeUser(agent, out reason)) | ||
3880 | return false; | ||
3881 | } | ||
3882 | } | ||
3883 | catch (Exception e) | ||
3781 | { | 3884 | { |
3782 | m_log.ErrorFormat( | 3885 | m_log.ErrorFormat( |
3783 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); | 3886 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); |
3784 | return false; | 3887 | return false; |
3785 | } | 3888 | } |
3786 | } | ||
3787 | 3889 | ||
3788 | try | 3890 | m_log.InfoFormat( |
3789 | { | 3891 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", |
3790 | // Always check estate if this is a login. Always | 3892 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, |
3791 | // check if banned regions are to be blacked out. | 3893 | agent.AgentID, agent.circuitcode); |
3792 | if (vialogin || (!m_seeIntoBannedRegion)) | 3894 | |
3895 | if (CapsModule != null) | ||
3793 | { | 3896 | { |
3794 | if (!AuthorizeUser(agent, out reason)) | 3897 | CapsModule.SetAgentCapsSeeds(agent); |
3795 | return false; | 3898 | CapsModule.CreateCaps(agent.AgentID); |
3796 | } | 3899 | } |
3797 | } | 3900 | } |
3798 | catch (Exception e) | 3901 | else |
3799 | { | 3902 | { |
3800 | m_log.ErrorFormat( | 3903 | // Let the SP know how we got here. This has a lot of interesting |
3801 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); | 3904 | // uses down the line. |
3802 | return false; | 3905 | sp.TeleportFlags = (TPFlags)teleportFlags; |
3803 | } | ||
3804 | |||
3805 | m_log.InfoFormat( | ||
3806 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", | ||
3807 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, | ||
3808 | agent.AgentID, agent.circuitcode); | ||
3809 | 3906 | ||
3810 | if (CapsModule != null) | 3907 | if (sp.IsChildAgent) |
3811 | { | 3908 | { |
3812 | CapsModule.SetAgentCapsSeeds(agent); | 3909 | m_log.DebugFormat( |
3813 | CapsModule.CreateCaps(agent.AgentID); | 3910 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", |
3814 | } | 3911 | agent.AgentID, RegionInfo.RegionName); |
3815 | } else | ||
3816 | { | ||
3817 | // Let the SP know how we got here. This has a lot of interesting | ||
3818 | // uses down the line. | ||
3819 | sp.TeleportFlags = (TPFlags)teleportFlags; | ||
3820 | 3912 | ||
3821 | if (sp.IsChildAgent) | 3913 | sp.AdjustKnownSeeds(); |
3822 | { | ||
3823 | m_log.DebugFormat( | ||
3824 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", | ||
3825 | agent.AgentID, RegionInfo.RegionName); | ||
3826 | 3914 | ||
3827 | sp.AdjustKnownSeeds(); | 3915 | if (CapsModule != null) |
3828 | 3916 | CapsModule.SetAgentCapsSeeds(agent); | |
3829 | if (CapsModule != null) | 3917 | } |
3830 | CapsModule.SetAgentCapsSeeds(agent); | ||
3831 | } | 3918 | } |
3832 | } | 3919 | } |
3833 | 3920 | ||