diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index c1bd07886d..af76ea9825 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -749,14 +749,21 @@ namespace OpenSim.Framework
///
string Name { get; }
- ///
- /// Determines whether the client thread is doing anything or not.
- ///
+ ///
+ /// True if the client is active (sending and receiving new UDP messages). False if the client is being closed.
+ ///
bool IsActive { get; set; }
- ///
- /// Determines whether the client is or has been removed from a given scene
- ///
+ ///
+ /// Set if the client is closing due to a logout request
+ ///
+ ///
+ /// Do not use this flag if you want to know if the client is closing, since it will not be set in other
+ /// circumstances (e.g. if a child agent is closed or the agent is kicked off the simulator). Use IsActive
+ /// instead with a IClientAPI.SceneAgent.IsChildAgent check if necessary.
+ ///
+ /// Only set for root agents.
+ ///
bool IsLoggingOut { get; set; }
bool SendLogoutPacketWhenClosing { set; }
diff --git a/OpenSim/Framework/ISceneAgent.cs b/OpenSim/Framework/ISceneAgent.cs
index 824172d58a..563d906b7f 100644
--- a/OpenSim/Framework/ISceneAgent.cs
+++ b/OpenSim/Framework/ISceneAgent.cs
@@ -26,6 +26,7 @@
*/
using System;
+using OpenMetaverse;
namespace OpenSim.Framework
{
@@ -71,5 +72,11 @@ namespace OpenSim.Framework
/// This includes scene object data and the appearance data of other avatars.
///
void SendInitialDataToMe();
+
+ ///
+ /// Direction in which the scene presence is looking.
+ ///
+ /// Will be Vector3.Zero for a child agent.
+ Vector3 Lookat { get; }
}
}
\ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 18d8045fe0..b40eeed41d 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -515,6 +515,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
public void Close(bool sendStop)
{
+ IsActive = false;
+
m_log.DebugFormat(
"[CLIENT]: Close has been called for {0} attached to scene {1}",
Name, m_scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 3c23dcff8d..22cc1940bd 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -555,12 +555,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (udpClient.IsPaused)
timeoutTicks = m_pausedAckTimeout;
- if (!client.IsLoggingOut &&
+ if (client.IsActive &&
(Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks)
{
- m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID);
- StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
- RemoveClient(client);
+ // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
+ // though it's set later on by LLClientView.Close()
+ client.IsActive = false;
+
+ // Fire this out on a different thread so that we don't hold up outgoing packet processing for
+ // everybody else if this is being called due to an ack timeout.
+ // This is the same as processing as the async process of a logout request.
+ Util.FireAndForget(o => DeactivateClientDueToTimeout(client));
return;
}
@@ -1110,9 +1115,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return client;
}
- private void RemoveClient(IClientAPI client)
+ ///
+ /// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds).
+ ///
+ ///
+ /// If a connection is active then we will always receive packets even if nothing else is happening, due to
+ /// regular client pings.
+ ///
+ ///
+ private void DeactivateClientDueToTimeout(IClientAPI client)
{
- client.IsLoggingOut = true;
+ // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
+ // though it's set later on by LLClientView.Close()
+ client.IsActive = false;
+
+ m_log.WarnFormat(
+ "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
+ client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
+
+ StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
+
+ if (!client.SceneAgent.IsChildAgent)
+ client.Kick("Simulator logged you out due to connection timeout");
+
Util.FireAndForget(o => client.Close());
}
@@ -1429,8 +1454,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected void LogoutHandler(IClientAPI client)
{
client.SendLogoutPacket();
+
if (!client.IsLoggingOut)
- RemoveClient(client);
+ {
+ client.IsLoggingOut = true;
+ client.Close();
+ }
}
}
}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 7e71fd18eb..3010b59f13 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -328,34 +328,30 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
void OnConnectionClosed(IClientAPI obj)
{
- if (obj.IsLoggingOut)
+ if (obj.SceneAgent.IsChildAgent)
+ return;
+
+ // Let's find out if this is a foreign user or a local user
+ IUserManagement uMan = Scene.RequestModuleInterface();
+// UserAccount account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, obj.AgentId);
+
+ if (uMan != null && uMan.IsLocalGridUser(obj.AgentId))
{
- object sp = null;
- if (obj.Scene.TryGetScenePresence(obj.AgentId, out sp))
- {
- if (((ScenePresence)sp).IsChildAgent)
- return;
- }
+ // local grid user
+ return;
+ }
- // Let's find out if this is a foreign user or a local user
- IUserManagement uMan = Scene.RequestModuleInterface();
-// UserAccount account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, obj.AgentId);
- if (uMan != null && uMan.IsLocalGridUser(obj.AgentId))
- {
- // local grid user
- return;
- }
+ AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode);
- AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode);
-
- if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
- {
- string url = aCircuit.ServiceURLs["HomeURI"].ToString();
- IUserAgentService security = new UserAgentServiceConnector(url);
- security.LogoutAgent(obj.AgentId, obj.SessionId);
- //m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Sent logout call to UserAgentService @ {0}", url);
- }
- else
+ if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
+ {
+ string url = aCircuit.ServiceURLs["HomeURI"].ToString();
+ IUserAgentService security = new UserAgentServiceConnector(url);
+ security.LogoutAgent(obj.AgentId, obj.SessionId);
+ //m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Sent logout call to UserAgentService @ {0}", url);
+ }
+ else
+ {
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: HomeURI not found for agent {0} logout", obj.AgentId);
}
}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index 4cf62eca54..b0edce7a91 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -79,29 +79,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
public void OnConnectionClose(IClientAPI client)
{
- if (client.IsLoggingOut)
- {
- object sp = null;
- Vector3 position = new Vector3(128, 128, 0);
- Vector3 lookat = new Vector3(0, 1, 0);
-
- if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
- {
- if (sp is ScenePresence)
- {
- if (((ScenePresence)sp).IsChildAgent)
- return;
-
- position = ((ScenePresence)sp).AbsolutePosition;
- lookat = ((ScenePresence)sp).Lookat;
- }
- }
-
-// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
- m_GridUserService.LoggedOut(client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, position, lookat);
- }
+ if (client.SceneAgent.IsChildAgent)
+ return;
+// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
+ m_GridUserService.LoggedOut(
+ client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID,
+ client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat);
}
-
}
}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
index ccfbf78a29..172bea10e3 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
@@ -64,7 +64,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
scene.EventManager.OnNewClient -= OnNewClient;
m_PresenceService.LogoutRegionAgents(scene.RegionInfo.RegionID);
-
}
public void OnMakeRootAgent(ScenePresence sp)
@@ -80,18 +79,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
public void OnConnectionClose(IClientAPI client)
{
- if (client.IsLoggingOut)
+ if (!client.SceneAgent.IsChildAgent)
{
- object sp = null;
- if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
- {
- if (sp is ScenePresence)
- {
- if (((ScenePresence)sp).IsChildAgent)
- return;
- }
- }
-
// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
m_PresenceService.LogoutAgent(client.SessionId);
}
diff --git a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
index 9cb567430b..d9d2e64d87 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
@@ -137,7 +137,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- if (fh.Client.IsLoggingOut)
+ if (!fh.Client.IsActive)
continue;
// m_log.DebugFormat(
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 3095382262..85bae9ab63 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3617,10 +3617,9 @@ namespace OpenSim.Region.Framework.Scenes
// 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
- );
+ "[SCENE]: Zombie scene presence detected for {0} {1} in {2}",
+ sp.Name, sp.UUID, RegionInfo.RegionName);
+
sp.ControllingClient.Close();
sp = null;
}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs
index 2267325bdc..95e4bab134 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs
@@ -79,27 +79,13 @@ namespace OpenSim.Services.Connectors.SimianGrid
public void OnConnectionClose(IClientAPI client)
{
- if (client.IsLoggingOut)
- {
- object sp = null;
- Vector3 position = new Vector3(128, 128, 0);
- Vector3 lookat = new Vector3(0, 1, 0);
+ if (client.SceneAgent.IsChildAgent)
+ return;
- if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
- {
- if (sp is ScenePresence)
- {
- if (((ScenePresence)sp).IsChildAgent)
- return;
-
- position = ((ScenePresence)sp).AbsolutePosition;
- lookat = ((ScenePresence)sp).Lookat;
- }
- }
-
-// m_log.DebugFormat("[SIMIAN ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
- m_GridUserService.LoggedOut(client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, position, lookat);
- }
+// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
+ m_GridUserService.LoggedOut(
+ client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID,
+ client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat);
}
void OnEnteringNewParcel(ScenePresence sp, int localLandID, UUID regionID)
@@ -111,4 +97,4 @@ namespace OpenSim.Services.Connectors.SimianGrid
});
}
}
-}
+}
\ No newline at end of file