diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 522 |
1 files changed, 310 insertions, 212 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 671feda..5f45529 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; } |
@@ -301,6 +306,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
301 | } | 306 | } |
302 | private volatile bool m_shuttingDown; | 307 | private volatile bool m_shuttingDown; |
303 | 308 | ||
309 | /// <summary> | ||
310 | /// Is the scene active? | ||
311 | /// </summary> | ||
312 | /// <remarks> | ||
313 | /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if | ||
314 | /// the scene is not active. | ||
315 | /// </remarks> | ||
316 | public bool Active | ||
317 | { | ||
318 | get { return m_active; } | ||
319 | set | ||
320 | { | ||
321 | if (value) | ||
322 | { | ||
323 | if (!m_active) | ||
324 | Start(); | ||
325 | } | ||
326 | else | ||
327 | { | ||
328 | m_active = false; | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | private volatile bool m_active; | ||
333 | |||
304 | // private int m_lastUpdate; | 334 | // private int m_lastUpdate; |
305 | // private bool m_firstHeartbeat = true; | 335 | // private bool m_firstHeartbeat = true; |
306 | 336 | ||
@@ -1154,6 +1184,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1154 | 1184 | ||
1155 | public void SetSceneCoreDebug(Dictionary<string, string> options) | 1185 | public void SetSceneCoreDebug(Dictionary<string, string> options) |
1156 | { | 1186 | { |
1187 | if (options.ContainsKey("active")) | ||
1188 | { | ||
1189 | bool active; | ||
1190 | |||
1191 | if (bool.TryParse(options["active"], out active)) | ||
1192 | Active = active; | ||
1193 | } | ||
1194 | |||
1157 | if (options.ContainsKey("scripting")) | 1195 | if (options.ContainsKey("scripting")) |
1158 | { | 1196 | { |
1159 | bool enableScripts = true; | 1197 | bool enableScripts = true; |
@@ -1293,6 +1331,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1293 | /// </summary> | 1331 | /// </summary> |
1294 | public void Start() | 1332 | public void Start() |
1295 | { | 1333 | { |
1334 | m_active = true; | ||
1335 | |||
1296 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); | 1336 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); |
1297 | 1337 | ||
1298 | //m_heartbeatTimer.Enabled = true; | 1338 | //m_heartbeatTimer.Enabled = true; |
@@ -1334,7 +1374,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1334 | #region Update Methods | 1374 | #region Update Methods |
1335 | 1375 | ||
1336 | /// <summary> | 1376 | /// <summary> |
1337 | /// Performs per-frame updates regularly | 1377 | /// Activate the various loops necessary to continually update the scene. |
1338 | /// </summary> | 1378 | /// </summary> |
1339 | private void Heartbeat() | 1379 | private void Heartbeat() |
1340 | { | 1380 | { |
@@ -1391,7 +1431,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1391 | List<Vector3> coarseLocations; | 1431 | List<Vector3> coarseLocations; |
1392 | List<UUID> avatarUUIDs; | 1432 | List<UUID> avatarUUIDs; |
1393 | 1433 | ||
1394 | while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) | 1434 | while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) |
1395 | { | 1435 | { |
1396 | runtc = Util.EnvironmentTickCount(); | 1436 | runtc = Util.EnvironmentTickCount(); |
1397 | ++MaintenanceRun; | 1437 | ++MaintenanceRun; |
@@ -1450,7 +1490,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1450 | int previousFrameTick, tmpMS; | 1490 | int previousFrameTick, tmpMS; |
1451 | int maintc = Util.EnvironmentTickCount(); | 1491 | int maintc = Util.EnvironmentTickCount(); |
1452 | 1492 | ||
1453 | while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) | 1493 | while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) |
1454 | { | 1494 | { |
1455 | ++Frame; | 1495 | ++Frame; |
1456 | 1496 | ||
@@ -2709,69 +2749,89 @@ namespace OpenSim.Region.Framework.Scenes | |||
2709 | 2749 | ||
2710 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) | 2750 | public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) |
2711 | { | 2751 | { |
2752 | ScenePresence sp; | ||
2753 | bool vialogin; | ||
2754 | |||
2712 | // Validation occurs in LLUDPServer | 2755 | // Validation occurs in LLUDPServer |
2756 | // | ||
2757 | // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with | ||
2758 | // each other. In practice, this does not currently occur in the code. | ||
2713 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); | 2759 | AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); |
2714 | 2760 | ||
2715 | bool vialogin | 2761 | // 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 | 2762 | // 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; | 2763 | // whilst connecting). |
2718 | 2764 | // | |
2719 | // CheckHeartbeat(); | 2765 | // It would be easier to lock across all NewUserConnection(), AddNewClient() and |
2720 | 2766 | // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service | |
2721 | ScenePresence sp = GetScenePresence(client.AgentId); | 2767 | // response in some module listening to AddNewClient()) from holding up unrelated agent calls. |
2722 | 2768 | // | |
2723 | // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this | 2769 | // 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 | 2770 | // AddNewClient() operations (though not other ops). |
2725 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already | 2771 | // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. |
2726 | // connected. | 2772 | lock (aCircuit) |
2727 | if (sp == null) | 2773 | { |
2728 | { | 2774 | vialogin |
2729 | m_log.DebugFormat( | 2775 | = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 |
2730 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", | 2776 | || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; |
2731 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); | 2777 | |
2732 | 2778 | // CheckHeartbeat(); | |
2733 | m_clientManager.Add(client); | 2779 | |
2734 | SubscribeToClientEvents(client); | 2780 | 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 | 2781 | ||
2741 | // The first agent upon login is a root agent by design. | 2782 | // 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. | 2783 | // 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. | 2784 | // other problems, and possible the code calling AddNewClient() should ensure that no client is already |
2744 | if (aCircuit.child == false) | 2785 | // connected. |
2786 | if (sp == null) | ||
2745 | { | 2787 | { |
2746 | // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to | 2788 | m_log.DebugFormat( |
2747 | // start the scripts again (since this is done in RezAttachments()). | 2789 | "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", |
2748 | // XXX: This is convoluted. | 2790 | client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); |
2749 | sp.IsChildAgent = false; | 2791 | |
2750 | 2792 | m_clientManager.Add(client); | |
2751 | if (AttachmentsModule != null) | 2793 | SubscribeToClientEvents(client); |
2752 | Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); | 2794 | |
2795 | sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); | ||
2796 | m_eventManager.TriggerOnNewPresence(sp); | ||
2797 | |||
2798 | sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; | ||
2799 | |||
2800 | // The first agent upon login is a root agent by design. | ||
2801 | // For this agent we will have to rez the attachments. | ||
2802 | // All other AddNewClient calls find aCircuit.child to be true. | ||
2803 | if (aCircuit.child == false) | ||
2804 | { | ||
2805 | // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to | ||
2806 | // start the scripts again (since this is done in RezAttachments()). | ||
2807 | // XXX: This is convoluted. | ||
2808 | sp.IsChildAgent = false; | ||
2809 | |||
2810 | if (AttachmentsModule != null) | ||
2811 | Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); | ||
2812 | } | ||
2753 | } | 2813 | } |
2754 | } | 2814 | else |
2755 | else | 2815 | { |
2756 | { | 2816 | m_log.WarnFormat( |
2757 | m_log.WarnFormat( | 2817 | "[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", | 2818 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); |
2759 | sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); | 2819 | } |
2760 | } | 2820 | |
2821 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | ||
2822 | // client is for a root or child agent. | ||
2823 | client.SceneAgent = sp; | ||
2761 | 2824 | ||
2762 | // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the | 2825 | // Cache the user's name |
2763 | // client is for a root or child agent. | 2826 | CacheUserName(sp, aCircuit); |
2764 | client.SceneAgent = sp; | 2827 | |
2828 | EventManager.TriggerOnNewClient(client); | ||
2829 | if (vialogin) | ||
2830 | EventManager.TriggerOnClientLogin(client); | ||
2831 | } | ||
2765 | 2832 | ||
2766 | m_LastLogin = Util.EnvironmentTickCount(); | 2833 | m_LastLogin = Util.EnvironmentTickCount(); |
2767 | 2834 | ||
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; | 2835 | return sp; |
2776 | } | 2836 | } |
2777 | 2837 | ||
@@ -3300,109 +3360,129 @@ namespace OpenSim.Region.Framework.Scenes | |||
3300 | { | 3360 | { |
3301 | // CheckHeartbeat(); | 3361 | // CheckHeartbeat(); |
3302 | bool isChildAgent = false; | 3362 | bool isChildAgent = false; |
3303 | ScenePresence avatar = GetScenePresence(agentID); | 3363 | AgentCircuitData acd; |
3304 | 3364 | ||
3305 | if (avatar == null) | 3365 | lock (m_removeClientLock) |
3306 | { | 3366 | { |
3307 | m_log.WarnFormat( | 3367 | acd = m_authenticateHandler.GetAgentCircuitData(agentID); |
3308 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); | ||
3309 | |||
3310 | return; | ||
3311 | } | ||
3312 | 3368 | ||
3313 | try | 3369 | if (acd == null) |
3314 | { | ||
3315 | isChildAgent = avatar.IsChildAgent; | ||
3316 | |||
3317 | m_log.DebugFormat( | ||
3318 | "[SCENE]: Removing {0} agent {1} {2} from {3}", | ||
3319 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); | ||
3320 | |||
3321 | // Don't do this to root agents, it's not nice for the viewer | ||
3322 | if (closeChildAgents && isChildAgent) | ||
3323 | { | 3370 | { |
3324 | // Tell a single agent to disconnect from the region. | 3371 | m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); |
3325 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | 3372 | return; |
3326 | if (eq != null) | ||
3327 | { | ||
3328 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); | ||
3329 | } | ||
3330 | else | ||
3331 | { | ||
3332 | avatar.ControllingClient.SendShutdownConnectionNotice(); | ||
3333 | } | ||
3334 | } | 3373 | } |
3335 | 3374 | else | |
3336 | // Only applies to root agents. | ||
3337 | if (avatar.ParentID != 0) | ||
3338 | { | 3375 | { |
3339 | avatar.StandUp(); | 3376 | // We remove the acd up here to avoid later raec conditions if two RemoveClient() calls occurred |
3377 | // simultaneously. | ||
3378 | m_authenticateHandler.RemoveCircuit(acd.circuitcode); | ||
3340 | } | 3379 | } |
3380 | } | ||
3341 | 3381 | ||
3342 | m_sceneGraph.removeUserCount(!isChildAgent); | 3382 | lock (acd) |
3343 | 3383 | { | |
3344 | // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop | 3384 | ScenePresence avatar = GetScenePresence(agentID); |
3345 | // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI | 3385 | |
3346 | if (closeChildAgents && CapsModule != null) | 3386 | 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 | { | 3387 | { |
3355 | List<ulong> regions = avatar.KnownRegionHandles; | 3388 | m_log.WarnFormat( |
3356 | regions.Remove(RegionInfo.RegionHandle); | 3389 | "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); |
3357 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | 3390 | |
3391 | return; | ||
3358 | } | 3392 | } |
3359 | 3393 | ||
3360 | m_eventManager.TriggerClientClosed(agentID, this); | 3394 | try |
3361 | m_eventManager.TriggerOnRemovePresence(agentID); | ||
3362 | |||
3363 | if (!isChildAgent) | ||
3364 | { | 3395 | { |
3365 | if (AttachmentsModule != null) | 3396 | isChildAgent = avatar.IsChildAgent; |
3397 | |||
3398 | m_log.DebugFormat( | ||
3399 | "[SCENE]: Removing {0} agent {1} {2} from {3}", | ||
3400 | (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); | ||
3401 | |||
3402 | // Don't do this to root agents, it's not nice for the viewer | ||
3403 | if (closeChildAgents && isChildAgent) | ||
3366 | { | 3404 | { |
3367 | AttachmentsModule.DeRezAttachments(avatar); | 3405 | // Tell a single agent to disconnect from the region. |
3406 | IEventQueue eq = RequestModuleInterface<IEventQueue>(); | ||
3407 | if (eq != null) | ||
3408 | { | ||
3409 | eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); | ||
3410 | } | ||
3411 | else | ||
3412 | { | ||
3413 | avatar.ControllingClient.SendShutdownConnectionNotice(); | ||
3414 | } | ||
3368 | } | 3415 | } |
3369 | 3416 | ||
3370 | ForEachClient( | 3417 | // Only applies to root agents. |
3371 | delegate(IClientAPI client) | 3418 | if (avatar.ParentID != 0) |
3419 | { | ||
3420 | avatar.StandUp(); | ||
3421 | } | ||
3422 | |||
3423 | m_sceneGraph.removeUserCount(!isChildAgent); | ||
3424 | |||
3425 | // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop | ||
3426 | // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI | ||
3427 | if (closeChildAgents && CapsModule != null) | ||
3428 | CapsModule.RemoveCaps(agentID); | ||
3429 | |||
3430 | // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever | ||
3431 | // this method is doing is HORRIBLE!!! | ||
3432 | avatar.Scene.NeedSceneCacheClear(avatar.UUID); | ||
3433 | |||
3434 | if (closeChildAgents && !isChildAgent) | ||
3435 | { | ||
3436 | List<ulong> regions = avatar.KnownRegionHandles; | ||
3437 | regions.Remove(RegionInfo.RegionHandle); | ||
3438 | m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); | ||
3439 | } | ||
3440 | |||
3441 | m_eventManager.TriggerClientClosed(agentID, this); | ||
3442 | m_eventManager.TriggerOnRemovePresence(agentID); | ||
3443 | |||
3444 | if (!isChildAgent) | ||
3445 | { | ||
3446 | if (AttachmentsModule != null) | ||
3372 | { | 3447 | { |
3373 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway | 3448 | AttachmentsModule.DeRezAttachments(avatar); |
3374 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } | 3449 | } |
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 | 3450 | ||
3383 | m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); | 3451 | ForEachClient( |
3384 | } | 3452 | delegate(IClientAPI client) |
3385 | catch (Exception e) | 3453 | { |
3386 | { | 3454 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway |
3387 | m_log.Error( | 3455 | 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); | 3456 | catch (NullReferenceException) { } |
3389 | } | 3457 | }); |
3390 | finally | 3458 | } |
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 | 3459 | ||
3400 | avatar.Close(); | 3460 | // It's possible for child agents to have transactions if changes are being made cross-border. |
3461 | if (AgentTransactionsModule != null) | ||
3462 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); | ||
3401 | } | 3463 | } |
3402 | catch (Exception e) | 3464 | catch (Exception e) |
3403 | { | 3465 | { |
3404 | m_log.Error( | 3466 | m_log.Error( |
3405 | string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); | 3467 | string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); |
3468 | } | ||
3469 | finally | ||
3470 | { | ||
3471 | try | ||
3472 | { | ||
3473 | // Always clean these structures up so that any failure above doesn't cause them to remain in the | ||
3474 | // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering | ||
3475 | // the same cleanup exception continually. | ||
3476 | m_sceneGraph.RemoveScenePresence(agentID); | ||
3477 | m_clientManager.Remove(agentID); | ||
3478 | |||
3479 | avatar.Close(); | ||
3480 | } | ||
3481 | catch (Exception e) | ||
3482 | { | ||
3483 | m_log.Error( | ||
3484 | string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); | ||
3485 | } | ||
3406 | } | 3486 | } |
3407 | } | 3487 | } |
3408 | 3488 | ||
@@ -3461,11 +3541,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3461 | 3541 | ||
3462 | /// <summary> | 3542 | /// <summary> |
3463 | /// Do the work necessary to initiate a new user connection for a particular scene. | 3543 | /// Do the work necessary to initiate a new user connection for a particular scene. |
3464 | /// At the moment, this consists of setting up the caps infrastructure | ||
3465 | /// The return bool should allow for connections to be refused, but as not all calling paths | ||
3466 | /// take proper notice of it let, we allowed banned users in still. | ||
3467 | /// </summary> | 3544 | /// </summary> |
3468 | /// <param name="agent">CircuitData of the agent who is connecting</param> | 3545 | /// <param name="agent">CircuitData of the agent who is connecting</param> |
3546 | /// <param name="teleportFlags"></param> | ||
3469 | /// <param name="reason">Outputs the reason for the false response on this string</param> | 3547 | /// <param name="reason">Outputs the reason for the false response on this string</param> |
3470 | /// <returns>True if the region accepts this agent. False if it does not. False will | 3548 | /// <returns>True if the region accepts this agent. False if it does not. False will |
3471 | /// also return a reason.</returns> | 3549 | /// also return a reason.</returns> |
@@ -3476,10 +3554,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
3476 | 3554 | ||
3477 | /// <summary> | 3555 | /// <summary> |
3478 | /// Do the work necessary to initiate a new user connection for a particular scene. | 3556 | /// Do the work necessary to initiate a new user connection for a particular scene. |
3479 | /// At the moment, this consists of setting up the caps infrastructure | 3557 | /// </summary> |
3558 | /// <remarks> | ||
3559 | /// The return bool should allow for connections to be refused, but as not all calling paths | ||
3560 | /// take proper notice of it yet, we still allowed banned users in. | ||
3561 | /// | ||
3562 | /// At the moment this method consists of setting up the caps infrastructure | ||
3480 | /// The return bool should allow for connections to be refused, but as not all calling paths | 3563 | /// The return bool should allow for connections to be refused, but as not all calling paths |
3481 | /// take proper notice of it let, we allowed banned users in still. | 3564 | /// take proper notice of it let, we allowed banned users in still. |
3482 | /// </summary> | 3565 | /// |
3566 | /// This method is called by the login service (in the case of login) or another simulator (in the case of region | ||
3567 | /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection | ||
3568 | /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of | ||
3569 | /// the LLUDP stack). | ||
3570 | /// </remarks> | ||
3483 | /// <param name="agent">CircuitData of the agent who is connecting</param> | 3571 | /// <param name="agent">CircuitData of the agent who is connecting</param> |
3484 | /// <param name="reason">Outputs the reason for the false response on this string</param> | 3572 | /// <param name="reason">Outputs the reason for the false response on this string</param> |
3485 | /// <param name="requirePresenceLookup">True for normal presence. False for NPC | 3573 | /// <param name="requirePresenceLookup">True for normal presence. False for NPC |
@@ -3564,88 +3652,97 @@ namespace OpenSim.Region.Framework.Scenes | |||
3564 | agent.firstname, agent.lastname, agent.Viewer); | 3652 | agent.firstname, agent.lastname, agent.Viewer); |
3565 | reason = "Access denied, your viewer is banned by the region owner"; | 3653 | reason = "Access denied, your viewer is banned by the region owner"; |
3566 | return false; | 3654 | return false; |
3567 | } | ||
3568 | |||
3569 | |||
3570 | ScenePresence sp = GetScenePresence(agent.AgentID); | ||
3571 | |||
3572 | if (sp != null && !sp.IsChildAgent) | ||
3573 | { | ||
3574 | // We have a zombie from a crashed session. | ||
3575 | // Or the same user is trying to be root twice here, won't work. | ||
3576 | // Kill it. | ||
3577 | m_log.WarnFormat( | ||
3578 | "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", | ||
3579 | sp.Name, sp.UUID, RegionInfo.RegionName); | ||
3580 | |||
3581 | sp.ControllingClient.Close(true); | ||
3582 | sp = null; | ||
3583 | } | 3655 | } |
3584 | 3656 | ||
3585 | ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); | 3657 | ILandObject land; |
3586 | 3658 | ||
3587 | //On login test land permisions | 3659 | lock (agent) |
3588 | if (vialogin) | ||
3589 | { | 3660 | { |
3590 | if (land != null && !TestLandRestrictions(agent, land, out reason)) | 3661 | ScenePresence sp = GetScenePresence(agent.AgentID); |
3662 | |||
3663 | if (sp != null && !sp.IsChildAgent) | ||
3591 | { | 3664 | { |
3592 | return false; | 3665 | // We have a zombie from a crashed session. |
3666 | // Or the same user is trying to be root twice here, won't work. | ||
3667 | // Kill it. | ||
3668 | m_log.WarnFormat( | ||
3669 | "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", | ||
3670 | sp.Name, sp.UUID, RegionInfo.RegionName); | ||
3671 | |||
3672 | sp.ControllingClient.Close(true); | ||
3673 | sp = null; | ||
3593 | } | 3674 | } |
3594 | } | 3675 | |
3595 | 3676 | land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); | |
3596 | if (sp == null) // We don't have an [child] agent here already | 3677 | |
3597 | { | 3678 | //On login test land permisions |
3598 | if (requirePresenceLookup) | 3679 | if (vialogin) |
3599 | { | 3680 | { |
3600 | try | 3681 | if (land != null && !TestLandRestrictions(agent, land, out reason)) |
3601 | { | 3682 | { |
3602 | if (!VerifyUserPresence(agent, out reason)) | ||
3603 | return false; | ||
3604 | } catch (Exception e) | ||
3605 | { | ||
3606 | m_log.ErrorFormat( | ||
3607 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); | ||
3608 | return false; | 3683 | return false; |
3609 | } | 3684 | } |
3610 | } | 3685 | } |
3611 | 3686 | ||
3612 | try | 3687 | if (sp == null) // We don't have an [child] agent here already |
3613 | { | ||
3614 | if (!AuthorizeUser(agent, out reason)) | ||
3615 | return false; | ||
3616 | } catch (Exception e) | ||
3617 | { | ||
3618 | m_log.ErrorFormat( | ||
3619 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); | ||
3620 | return false; | ||
3621 | } | ||
3622 | |||
3623 | m_log.InfoFormat( | ||
3624 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", | ||
3625 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, | ||
3626 | agent.AgentID, agent.circuitcode); | ||
3627 | |||
3628 | if (CapsModule != null) | ||
3629 | { | 3688 | { |
3630 | CapsModule.SetAgentCapsSeeds(agent); | 3689 | if (requirePresenceLookup) |
3631 | CapsModule.CreateCaps(agent.AgentID); | 3690 | { |
3632 | } | 3691 | try |
3633 | } else | 3692 | { |
3634 | { | 3693 | if (!VerifyUserPresence(agent, out reason)) |
3635 | // Let the SP know how we got here. This has a lot of interesting | 3694 | return false; |
3636 | // uses down the line. | 3695 | } |
3637 | sp.TeleportFlags = (TPFlags)teleportFlags; | 3696 | catch (Exception e) |
3697 | { | ||
3698 | m_log.ErrorFormat( | ||
3699 | "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); | ||
3638 | 3700 | ||
3639 | if (sp.IsChildAgent) | 3701 | return false; |
3640 | { | 3702 | } |
3641 | m_log.DebugFormat( | 3703 | } |
3642 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", | 3704 | |
3643 | agent.AgentID, RegionInfo.RegionName); | 3705 | try |
3706 | { | ||
3707 | if (!AuthorizeUser(agent, out reason)) | ||
3708 | return false; | ||
3709 | } | ||
3710 | catch (Exception e) | ||
3711 | { | ||
3712 | m_log.ErrorFormat( | ||
3713 | "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); | ||
3644 | 3714 | ||
3645 | sp.AdjustKnownSeeds(); | 3715 | return false; |
3646 | 3716 | } | |
3717 | |||
3718 | m_log.InfoFormat( | ||
3719 | "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", | ||
3720 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, | ||
3721 | agent.AgentID, agent.circuitcode); | ||
3722 | |||
3647 | if (CapsModule != null) | 3723 | if (CapsModule != null) |
3724 | { | ||
3648 | CapsModule.SetAgentCapsSeeds(agent); | 3725 | CapsModule.SetAgentCapsSeeds(agent); |
3726 | CapsModule.CreateCaps(agent.AgentID); | ||
3727 | } | ||
3728 | } | ||
3729 | else | ||
3730 | { | ||
3731 | // Let the SP know how we got here. This has a lot of interesting | ||
3732 | // uses down the line. | ||
3733 | sp.TeleportFlags = (TPFlags)teleportFlags; | ||
3734 | |||
3735 | if (sp.IsChildAgent) | ||
3736 | { | ||
3737 | m_log.DebugFormat( | ||
3738 | "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", | ||
3739 | agent.AgentID, RegionInfo.RegionName); | ||
3740 | |||
3741 | sp.AdjustKnownSeeds(); | ||
3742 | |||
3743 | if (CapsModule != null) | ||
3744 | CapsModule.SetAgentCapsSeeds(agent); | ||
3745 | } | ||
3649 | } | 3746 | } |
3650 | } | 3747 | } |
3651 | 3748 | ||
@@ -4047,8 +4144,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
4047 | return false; | 4144 | return false; |
4048 | } | 4145 | } |
4049 | 4146 | ||
4050 | // We have to wait until the viewer contacts this region after receiving EAC. | 4147 | // We have to wait until the viewer contacts this region |
4051 | // That calls AddNewClient, which finally creates the ScenePresence | 4148 | // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send |
4149 | // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. | ||
4052 | ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); | 4150 | ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); |
4053 | 4151 | ||
4054 | if (childAgentUpdate != null) | 4152 | if (childAgentUpdate != null) |