diff options
3 files changed, 265 insertions, 219 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 594b229..0dd0904 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs | |||
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
94 | 94 | ||
95 | //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); | 95 | //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); |
96 | 96 | ||
97 | scene.EventManager.OnNewClient += OnNewClient; | 97 | // scene.EventManager.OnNewClient += OnNewClient; |
98 | 98 | ||
99 | // TODO: Leaving these open, or closing them when we | 99 | // TODO: Leaving these open, or closing them when we |
100 | // become a child is incorrect. It messes up TP in a big | 100 | // become a child is incorrect. It messes up TP in a big |
@@ -102,6 +102,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
102 | // circuit is there. | 102 | // circuit is there. |
103 | 103 | ||
104 | scene.EventManager.OnClientClosed += ClientClosed; | 104 | scene.EventManager.OnClientClosed += ClientClosed; |
105 | |||
105 | scene.EventManager.OnMakeChildAgent += MakeChildAgent; | 106 | scene.EventManager.OnMakeChildAgent += MakeChildAgent; |
106 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; | 107 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; |
107 | 108 | ||
@@ -226,16 +227,6 @@ namespace OpenSim.Region.ClientStack.Linden | |||
226 | 227 | ||
227 | #endregion | 228 | #endregion |
228 | 229 | ||
229 | private void OnNewClient(IClientAPI client) | ||
230 | { | ||
231 | //client.OnLogout += ClientClosed; | ||
232 | } | ||
233 | |||
234 | // private void ClientClosed(IClientAPI client) | ||
235 | // { | ||
236 | // ClientClosed(client.AgentId); | ||
237 | // } | ||
238 | |||
239 | private void ClientClosed(UUID agentID, Scene scene) | 230 | private void ClientClosed(UUID agentID, Scene scene) |
240 | { | 231 | { |
241 | // m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); | 232 | // m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index d11fcbf..ab670a7 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -1103,20 +1103,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1103 | { | 1103 | { |
1104 | IClientAPI client = null; | 1104 | IClientAPI client = null; |
1105 | 1105 | ||
1106 | // In priciple there shouldn't be more than one thread here, ever. | 1106 | // We currently synchronize this code across the whole scene to avoid issues such as |
1107 | // But in case that happens, we need to synchronize this piece of code | 1107 | // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done |
1108 | // because it's too important | 1108 | // consistently, this lock could probably be removed. |
1109 | lock (this) | 1109 | lock (this) |
1110 | { | 1110 | { |
1111 | if (!m_scene.TryGetClient(agentID, out client)) | 1111 | if (!m_scene.TryGetClient(agentID, out client)) |
1112 | { | 1112 | { |
1113 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); | 1113 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); |
1114 | 1114 | ||
1115 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); | 1115 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); |
1116 | client.OnLogout += LogoutHandler; | 1116 | client.OnLogout += LogoutHandler; |
1117 | 1117 | ||
1118 | ((LLClientView)client).DisableFacelights = m_disableFacelights; | 1118 | ((LLClientView)client).DisableFacelights = m_disableFacelights; |
1119 | 1119 | ||
1120 | client.Start(); | 1120 | client.Start(); |
1121 | } | 1121 | } |
1122 | } | 1122 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ed88571..fb2decc 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; } |
@@ -2709,69 +2714,89 @@ namespace OpenSim.Region.Framework.Scenes | |||
2709 | 2714 | ||
2710 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) | 2715 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) |
2711 | { | 2716 | { |
2717 | ScenePresence sp; | ||
2718 | bool vialogin; | ||
2719 | |||
2712 | // Validation occurs in LLUDPServer | 2720 | // Validation occurs in LLUDPServer |
2721 | // | ||
2722 | // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with | ||
2723 | // each other. In practice, this does not currently occur in the code. | ||
2713 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); | 2724 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); |
2714 | 2725 | ||
2715 | bool vialogin | 2726 | // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection |
2716 | = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 | 2727 | // and a simultaneous one that removes it (as can happen if the client is closed at a particular point |
2717 | || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; | 2728 | // whilst connecting). |
2718 | 2729 | // | |
2719 | // CheckHeartbeat(); | 2730 | // It would be easier to lock across all NewUserConnection(), AddNewClient() and |
2720 | 2731 | // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service | |
2721 | ScenePresence sp = GetScenePresence(client.AgentId); | 2732 | // response in some module listening to AddNewClient()) from holding up unrelated agent calls. |
2722 | 2733 | // | |
2723 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this | 2734 | // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all |
2724 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause | 2735 | // AddNewClient() operations (though not other ops). |
2725 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already | 2736 | // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. |
2726 | // connected. | 2737 | lock (aCircuit) |
2727 | if (sp == null) | 2738 | { |
2728 | { | 2739 | vialogin |
2729 | m_log.DebugFormat( | 2740 | = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 |
2730 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", | 2741 | || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; |
2731 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); | 2742 | |
2732 | 2743 | // CheckHeartbeat(); | |
2733 | m_clientManager.Add(client); | 2744 | |
2734 | SubscribeToClientEvents(client); | 2745 | sp = GetScenePresence(client.AgentId); |
2735 | |||
2736 | sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); | ||
2737 | m_eventManager.TriggerOnNewPresence(sp); | ||
2738 | |||
2739 | sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; | ||
2740 | 2746 | ||
2741 | // The first agent upon login is a root agent by design. | 2747 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this |
2742 | // For this agent we will have to rez the attachments. | 2748 | // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause |
2743 | // All other AddNewClient calls find aCircuit.child to be true. | 2749 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already |
2744 | if (aCircuit.child == false) | 2750 | // connected. |
2751 | if (sp == null) | ||
2745 | { | 2752 | { |
2746 | // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to | 2753 | m_log.DebugFormat( |
2747 | // start the scripts again (since this is done in RezAttachments()). | 2754 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", |
2748 | // XXX: This is convoluted. | 2755 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); |
2749 | sp.IsChildAgent = false; | 2756 | |
2750 | 2757 | m_clientManager.Add(client); | |
2751 | if (AttachmentsModule != null) | 2758 | SubscribeToClientEvents(client); |
2752 | Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); | 2759 | |
2760 | sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); | ||
2761 | m_eventManager.TriggerOnNewPresence(sp); | ||
2762 | |||
2763 | sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; | ||
2764 | |||
2765 | // The first agent upon login is a root agent by design. | ||
2766 | // For this agent we will have to rez the attachments. | ||
2767 | // All other AddNewClient calls find aCircuit.child to be true. | ||
2768 | if (aCircuit.child == false) | ||
2769 | { | ||
2770 | // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to | ||
2771 | // start the scripts again (since this is done in RezAttachments()). | ||
2772 | // XXX: This is convoluted. | ||
2773 | sp.IsChildAgent = false; | ||
2774 | |||
2775 | if (AttachmentsModule != null) | ||
2776 | Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); | ||
2777 | } | ||
2753 | } | 2778 | } |
2754 | } | 2779 | else |
2755 | else | 2780 | { |
2756 | { | 2781 | m_log.WarnFormat( |
2757 | m_log.WarnFormat( | 2782 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", |
2758 | "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", | 2783 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); |
2759 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); | 2784 | } |
2760 | } | 2785 | |
2786 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | ||
2787 | // client is for a root or child agent. | ||
2788 | client.SceneAgent = sp; | ||
2761 | 2789 | ||
2762 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | 2790 | // Cache the user's name |
2763 | // client is for a root or child agent. | 2791 | CacheUserName(sp, aCircuit); |
2764 | client.SceneAgent = sp; | 2792 | |
2793 | EventManager.TriggerOnNewClient(client); | ||
2794 | if (vialogin) | ||
2795 | EventManager.TriggerOnClientLogin(client); | ||
2796 | } | ||
2765 | 2797 | ||
2766 | m_LastLogin = Util.EnvironmentTickCount(); | 2798 | m_LastLogin = Util.EnvironmentTickCount(); |
2767 | 2799 | ||
2768 | // Cache the user's name | ||
2769 | CacheUserName(sp, aCircuit); | ||
2770 | |||
2771 | EventManager.TriggerOnNewClient(client); | ||
2772 | if (vialogin) | ||
2773 | EventManager.TriggerOnClientLogin(client); | ||
2774 | |||
2775 | return sp; | 2800 | return sp; |
2776 | } | 2801 | } |
2777 | 2802 | ||
@@ -3300,109 +3325,129 @@ namespace OpenSim.Region.Framework.Scenes | |||
3300 | { | 3325 | { |
3301 | // CheckHeartbeat(); | 3326 | // CheckHeartbeat(); |
3302 | bool isChildAgent = false; | 3327 | bool isChildAgent = false; |
3303 | ScenePresence avatar = GetScenePresence(agentID); | 3328 | AgentCircuitData acd; |
3304 | |||
3305 | if (avatar == null) | ||
3306 | { | ||
3307 | m_log.WarnFormat( | ||
3308 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); | ||
3309 | |||
3310 | return; | ||
3311 | } | ||
3312 | 3329 | ||
3313 | try | 3330 | lock (m_removeClientLock) |
3314 | { | 3331 | { |
3315 | isChildAgent = avatar.IsChildAgent; | 3332 | acd = m_authenticateHandler.GetAgentCircuitData(agentID); |
3316 | |||
3317 | m_log.DebugFormat( | ||
3318 | "[SCENE]: Removing {0} agent {1} {2} from {3}", | ||
3319 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); | ||
3320 | 3333 | ||
3321 | // Don't do this to root agents, it's not nice for the viewer | 3334 | if (acd == null) |
3322 | if (closeChildAgents && isChildAgent) | ||
3323 | { | 3335 | { |
3324 | // Tell a single agent to disconnect from the region. | 3336 | m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); |
3325 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | 3337 | return; |
3326 | if (eq != null) | ||
3327 | { | ||
3328 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); | ||
3329 | } | ||
3330 | else | ||
3331 | { | ||
3332 | avatar.ControllingClient.SendShutdownConnectionNotice(); | ||
3333 | } | ||
3334 | } | 3338 | } |
3335 | 3339 | else | |
3336 | // Only applies to root agents. | ||
3337 | if (avatar.ParentID != 0) | ||
3338 | { | 3340 | { |
3339 | avatar.StandUp(); | 3341 | // We remove the acd up here to avoid later raec conditions if two RemoveClient() calls occurred |
3342 | // simultaneously. | ||
3343 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); | ||
3340 | } | 3344 | } |
3345 | } | ||
3341 | 3346 | ||
3342 | m_sceneGraph.removeUserCount(!isChildAgent); | 3347 | lock (acd) |
3343 | 3348 | { | |
3344 | // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop | 3349 | ScenePresence avatar = GetScenePresence(agentID); |
3345 | // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI | 3350 | |
3346 | if (closeChildAgents && CapsModule != null) | 3351 | if (avatar == null) |
3347 | CapsModule.RemoveCaps(agentID); | ||
3348 | |||
3349 | // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | ||
3350 | // this method is doing is HORRIBLE!!! | ||
3351 | avatar.Scene.NeedSceneCacheClear(avatar.UUID); | ||
3352 | |||
3353 | if (closeChildAgents && !isChildAgent) | ||
3354 | { | 3352 | { |
3355 | List<ulong> regions = avatar.KnownRegionHandles; | 3353 | m_log.WarnFormat( |
3356 | regions.Remove(RegionInfo.RegionHandle); | 3354 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); |
3357 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | 3355 | |
3356 | return; | ||
3358 | } | 3357 | } |
3359 | 3358 | ||
3360 | m_eventManager.TriggerClientClosed(agentID, this); | 3359 | try |
3361 | m_eventManager.TriggerOnRemovePresence(agentID); | ||
3362 | |||
3363 | if (!isChildAgent) | ||
3364 | { | 3360 | { |
3365 | if (AttachmentsModule != null) | 3361 | isChildAgent = avatar.IsChildAgent; |
3362 | |||
3363 | m_log.DebugFormat( | ||
3364 | "[SCENE]: Removing {0} agent {1} {2} from {3}", | ||
3365 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); | ||
3366 | |||
3367 | // Don't do this to root agents, it's not nice for the viewer | ||
3368 | if (closeChildAgents && isChildAgent) | ||
3366 | { | 3369 | { |
3367 | AttachmentsModule.DeRezAttachments(avatar); | 3370 | // Tell a single agent to disconnect from the region. |
3371 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | ||
3372 | if (eq != null) | ||
3373 | { | ||
3374 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); | ||
3375 | } | ||
3376 | else | ||
3377 | { | ||
3378 | avatar.ControllingClient.SendShutdownConnectionNotice(); | ||
3379 | } | ||
3368 | } | 3380 | } |
3369 | 3381 | ||
3370 | ForEachClient( | 3382 | // Only applies to root agents. |
3371 | delegate(IClientAPI client) | 3383 | if (avatar.ParentID != 0) |
3384 | { | ||
3385 | avatar.StandUp(); | ||
3386 | } | ||
3387 | |||
3388 | m_sceneGraph.removeUserCount(!isChildAgent); | ||
3389 | |||
3390 | // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop | ||
3391 | // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI | ||
3392 | if (closeChildAgents && CapsModule != null) | ||
3393 | CapsModule.RemoveCaps(agentID); | ||
3394 | |||
3395 | // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | ||
3396 | // this method is doing is HORRIBLE!!! | ||
3397 | avatar.Scene.NeedSceneCacheClear(avatar.UUID); | ||
3398 | |||
3399 | if (closeChildAgents && !isChildAgent) | ||
3400 | { | ||
3401 | List<ulong> regions = avatar.KnownRegionHandles; | ||
3402 | regions.Remove(RegionInfo.RegionHandle); | ||
3403 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | ||
3404 | } | ||
3405 | |||
3406 | m_eventManager.TriggerClientClosed(agentID, this); | ||
3407 | m_eventManager.TriggerOnRemovePresence(agentID); | ||
3408 | |||
3409 | if (!isChildAgent) | ||
3410 | { | ||
3411 | if (AttachmentsModule != null) | ||
3372 | { | 3412 | { |
3373 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway | 3413 | AttachmentsModule.DeRezAttachments(avatar); |
3374 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } | 3414 | } |
3375 | catch (NullReferenceException) { } | ||
3376 | }); | ||
3377 | } | ||
3378 | |||
3379 | // It's possible for child agents to have transactions if changes are being made cross-border. | ||
3380 | if (AgentTransactionsModule != null) | ||
3381 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); | ||
3382 | 3415 | ||
3383 | m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); | 3416 | ForEachClient( |
3384 | } | 3417 | delegate(IClientAPI client) |
3385 | catch (Exception e) | 3418 | { |
3386 | { | 3419 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway |
3387 | m_log.Error( | 3420 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } |
3388 | string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); | 3421 | catch (NullReferenceException) { } |
3389 | } | 3422 | }); |
3390 | finally | 3423 | } |
3391 | { | ||
3392 | try | ||
3393 | { | ||
3394 | // Always clean these structures up so that any failure above doesn't cause them to remain in the | ||
3395 | // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering | ||
3396 | // the same cleanup exception continually. | ||
3397 | m_sceneGraph.RemoveScenePresence(agentID); | ||
3398 | m_clientManager.Remove(agentID); | ||
3399 | 3424 | ||
3400 | avatar.Close(); | 3425 | // It's possible for child agents to have transactions if changes are being made cross-border. |
3426 | if (AgentTransactionsModule != null) | ||
3427 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); | ||
3401 | } | 3428 | } |
3402 | catch (Exception e) | 3429 | catch (Exception e) |
3403 | { | 3430 | { |
3404 | m_log.Error( | 3431 | m_log.Error( |
3405 | string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); | 3432 | string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); |
3433 | } | ||
3434 | finally | ||
3435 | { | ||
3436 | try | ||
3437 | { | ||
3438 | // Always clean these structures up so that any failure above doesn't cause them to remain in the | ||
3439 | // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering | ||
3440 | // the same cleanup exception continually. | ||
3441 | m_sceneGraph.RemoveScenePresence(agentID); | ||
3442 | m_clientManager.Remove(agentID); | ||
3443 | |||
3444 | avatar.Close(); | ||
3445 | } | ||
3446 | catch (Exception e) | ||
3447 | { | ||
3448 | m_log.Error( | ||
3449 | string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); | ||
3450 | } | ||
3406 | } | 3451 | } |
3407 | } | 3452 | } |
3408 | 3453 | ||
@@ -3572,87 +3617,97 @@ namespace OpenSim.Region.Framework.Scenes | |||
3572 | agent.firstname, agent.lastname, agent.Viewer); | 3617 | agent.firstname, agent.lastname, agent.Viewer); |
3573 | reason = "Access denied, your viewer is banned by the region owner"; | 3618 | reason = "Access denied, your viewer is banned by the region owner"; |
3574 | return false; | 3619 | return false; |
3575 | } | ||
3576 | |||
3577 | ScenePresence sp = GetScenePresence(agent.AgentID); | ||
3578 | |||
3579 | if (sp != null && !sp.IsChildAgent) | ||
3580 | { | ||
3581 | // We have a zombie from a crashed session. | ||
3582 | // Or the same user is trying to be root twice here, won't work. | ||
3583 | // Kill it. | ||
3584 | m_log.WarnFormat( | ||
3585 | "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", | ||
3586 | sp.Name, sp.UUID, RegionInfo.RegionName); | ||
3587 | |||
3588 | sp.ControllingClient.Close(true); | ||
3589 | sp = null; | ||
3590 | } | 3620 | } |
3591 | 3621 | ||
3592 | ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); | 3622 | ILandObject land; |
3593 | 3623 | ||
3594 | //On login test land permisions | 3624 | lock (agent) |
3595 | if (vialogin) | ||
3596 | { | 3625 | { |
3597 | if (land != null && !TestLandRestrictions(agent, land, out reason)) | 3626 | ScenePresence sp = GetScenePresence(agent.AgentID); |
3627 | |||
3628 | if (sp != null && !sp.IsChildAgent) | ||
3598 | { | 3629 | { |
3599 | return false; | 3630 | // We have a zombie from a crashed session. |
3631 | // Or the same user is trying to be root twice here, won't work. | ||
3632 | // Kill it. | ||
3633 | m_log.WarnFormat( | ||
3634 | "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", | ||
3635 | sp.Name, sp.UUID, RegionInfo.RegionName); | ||
3636 | |||
3637 | sp.ControllingClient.Close(true); | ||
3638 | sp = null; | ||
3600 | } | 3639 | } |
3601 | } | 3640 | |
3602 | 3641 | land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); | |
3603 | if (sp == null) // We don't have an [child] agent here already | 3642 | |
3604 | { | 3643 | //On login test land permisions |
3605 | if (requirePresenceLookup) | 3644 | if (vialogin) |
3606 | { | 3645 | { |
3607 | try | 3646 | if (land != null && !TestLandRestrictions(agent, land, out reason)) |
3608 | { | ||
3609 | if (!VerifyUserPresence(agent, out reason)) | ||
3610 | return false; | ||
3611 | } catch (Exception e) | ||
3612 | { | 3647 | { |
3613 | m_log.ErrorFormat( | ||
3614 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); | ||
3615 | return false; | 3648 | return false; |
3616 | } | 3649 | } |
3617 | } | 3650 | } |
3618 | 3651 | ||
3619 | try | 3652 | if (sp == null) // We don't have an [child] agent here already |
3620 | { | ||
3621 | if (!AuthorizeUser(agent, out reason)) | ||
3622 | return false; | ||
3623 | } catch (Exception e) | ||
3624 | { | ||
3625 | m_log.ErrorFormat( | ||
3626 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); | ||
3627 | return false; | ||
3628 | } | ||
3629 | |||
3630 | m_log.InfoFormat( | ||
3631 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", | ||
3632 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, | ||
3633 | agent.AgentID, agent.circuitcode); | ||
3634 | |||
3635 | if (CapsModule != null) | ||
3636 | { | 3653 | { |
3637 | CapsModule.SetAgentCapsSeeds(agent); | 3654 | if (requirePresenceLookup) |
3638 | CapsModule.CreateCaps(agent.AgentID); | 3655 | { |
3639 | } | 3656 | try |
3640 | } else | 3657 | { |
3641 | { | 3658 | if (!VerifyUserPresence(agent, out reason)) |
3642 | // Let the SP know how we got here. This has a lot of interesting | 3659 | return false; |
3643 | // uses down the line. | 3660 | } |
3644 | sp.TeleportFlags = (TPFlags)teleportFlags; | 3661 | catch (Exception e) |
3662 | { | ||
3663 | m_log.ErrorFormat( | ||
3664 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); | ||
3645 | 3665 | ||
3646 | if (sp.IsChildAgent) | 3666 | return false; |
3647 | { | 3667 | } |
3648 | m_log.DebugFormat( | 3668 | } |
3649 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", | 3669 | |
3650 | agent.AgentID, RegionInfo.RegionName); | 3670 | try |
3671 | { | ||
3672 | if (!AuthorizeUser(agent, out reason)) | ||
3673 | return false; | ||
3674 | } | ||
3675 | catch (Exception e) | ||
3676 | { | ||
3677 | m_log.ErrorFormat( | ||
3678 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); | ||
3651 | 3679 | ||
3652 | sp.AdjustKnownSeeds(); | 3680 | return false; |
3653 | 3681 | } | |
3682 | |||
3683 | m_log.InfoFormat( | ||
3684 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", | ||
3685 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, | ||
3686 | agent.AgentID, agent.circuitcode); | ||
3687 | |||
3654 | if (CapsModule != null) | 3688 | if (CapsModule != null) |
3689 | { | ||
3655 | CapsModule.SetAgentCapsSeeds(agent); | 3690 | CapsModule.SetAgentCapsSeeds(agent); |
3691 | CapsModule.CreateCaps(agent.AgentID); | ||
3692 | } | ||
3693 | } | ||
3694 | else | ||
3695 | { | ||
3696 | // Let the SP know how we got here. This has a lot of interesting | ||
3697 | // uses down the line. | ||
3698 | sp.TeleportFlags = (TPFlags)teleportFlags; | ||
3699 | |||
3700 | if (sp.IsChildAgent) | ||
3701 | { | ||
3702 | m_log.DebugFormat( | ||
3703 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", | ||
3704 | agent.AgentID, RegionInfo.RegionName); | ||
3705 | |||
3706 | sp.AdjustKnownSeeds(); | ||
3707 | |||
3708 | if (CapsModule != null) | ||
3709 | CapsModule.SetAgentCapsSeeds(agent); | ||
3710 | } | ||
3656 | } | 3711 | } |
3657 | } | 3712 | } |
3658 | 3713 | ||