aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-06-12 02:16:36 +0100
committerJustin Clark-Casey (justincc)2012-06-12 02:16:36 +0100
commitb099f26376a7d671eeb9113dd7611cfcb0e57de0 (patch)
tree85e4f2bfb41e2f8b811a0acf6ba7d849e24918c7
parentIf the simulator closes a root agent due to ack timeout, then send the client... (diff)
downloadopensim-SC_OLD-b099f26376a7d671eeb9113dd7611cfcb0e57de0.zip
opensim-SC_OLD-b099f26376a7d671eeb9113dd7611cfcb0e57de0.tar.gz
opensim-SC_OLD-b099f26376a7d671eeb9113dd7611cfcb0e57de0.tar.bz2
opensim-SC_OLD-b099f26376a7d671eeb9113dd7611cfcb0e57de0.tar.xz
Set IClientAPI.IsActive = false early on client removal due to ack timeout rather than using IsLoggingOut flag.
IsActive is more appropriate since unack timeout is not due to voluntary logout. This is in line with operations such as manual kick that do not set the IsLoggingOut flag. It's also slightly better race-wise since it reduces the chance of this operation clashing with another reason for client deactivation (e.g. manual kick).
-rw-r--r--OpenSim/Framework/IClientAPI.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs64
2 files changed, 38 insertions, 35 deletions
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index f8b6a84..2ea6de5 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -741,22 +741,19 @@ namespace OpenSim.Framework
741 string Name { get; } 741 string Name { get; }
742 742
743 /// <summary> 743 /// <summary>
744 /// True if the client is active (sending and receiving new UDP messages). False if the client is closing. 744 /// True if the client is active (sending and receiving new UDP messages). False if the client is being closed.
745 /// </summary> 745 /// </summary>
746 bool IsActive { get; set; } 746 bool IsActive { get; set; }
747 747
748 /// <summary> 748 /// <summary>
749 /// Set if the client is closing due to a logout request or because of too much time since last ack. 749 /// Set if the client is closing due to a logout request
750 /// </summary> 750 /// </summary>
751 /// <remarks> 751 /// <remarks>
752 /// Do not use this flag if you want to know if the client is closing, since it will not be set in other 752 /// Do not use this flag if you want to know if the client is closing, since it will not be set in other
753 /// circumstances (e.g. if a child agent is closed or the agent is kicked off the simulator). Use IsActive 753 /// circumstances (e.g. if a child agent is closed or the agent is kicked off the simulator). Use IsActive
754 /// instead. 754 /// instead with a IClientAPI.SceneAgent.IsChildAgent check if necessary.
755 /// 755 ///
756 /// Only set for root agents. 756 /// Only set for root agents.
757 ///
758 /// TODO: Too much time since last ack should probably be a separate property, or possibly part of a state
759 /// machine.
760 /// </remarks> 757 /// </remarks>
761 bool IsLoggingOut { get; set; } 758 bool IsLoggingOut { get; set; }
762 759
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 2036f61..37d2943 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -555,15 +555,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
555 if (udpClient.IsPaused) 555 if (udpClient.IsPaused)
556 timeoutTicks = m_pausedAckTimeout; 556 timeoutTicks = m_pausedAckTimeout;
557 557
558 if (!client.IsLoggingOut && 558 if (client.IsActive &&
559 (Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks) 559 (Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks)
560 { 560 {
561 m_log.WarnFormat( 561 // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
562 "[LLUDPSERVER]: Ack timeout for {0} {1}, disconnecting", 562 // though it's set later on by LLClientView.Close()
563 client.Name, client.AgentId); 563 client.IsActive = false;
564 564
565 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); 565 // Fire this out on a different thread so that we don't hold up outgoing packet processing for
566 LogoutClientDueToTimeout(client); 566 // everybody else if this is being called due to an ack timeout.
567 // This is the same as processing as the async process of a logout request.
568 Util.FireAndForget(o => DeactivateClientDueToTimeout(client));
567 569
568 return; 570 return;
569 } 571 }
@@ -792,7 +794,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
792 Interlocked.Increment(ref udpClient.PacketsReceived); 794 Interlocked.Increment(ref udpClient.PacketsReceived);
793 795
794 int now = Environment.TickCount & Int32.MaxValue; 796 int now = Environment.TickCount & Int32.MaxValue;
795 udpClient.TickLastPacketReceived = now; 797// udpClient.TickLastPacketReceived = now;
796 798
797 #region ACK Receiving 799 #region ACK Receiving
798 800
@@ -1113,30 +1115,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1113 return client; 1115 return client;
1114 } 1116 }
1115 1117
1116 private void RemoveClient(IClientAPI client) 1118 /// <summary>
1119 /// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds).
1120 /// </summary>
1121 /// <remarks>
1122 /// If a connection is active then we will always receive packets even if nothing else is happening, due to
1123 /// regular client pings.
1124 /// </remarks>
1125 /// <param name='client'></param>
1126 private void DeactivateClientDueToTimeout(IClientAPI client)
1117 { 1127 {
1118 // We must set IsLoggingOut synchronously so that we can stop the packet loop reinvoking this method. 1128 // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
1119 client.IsLoggingOut = true; 1129 // though it's set later on by LLClientView.Close()
1130 client.IsActive = false;
1120 1131
1121 // Fire this out on a different thread so that we don't hold up outgoing packet processing for 1132 m_log.WarnFormat(
1122 // everybody else if this is being called due to an ack timeout. 1133 "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
1123 // This is the same as processing as the async process of a logout request. 1134 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
1124 Util.FireAndForget(o => client.Close());
1125 }
1126 1135
1127 private void LogoutClientDueToTimeout(IClientAPI client) 1136 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
1128 { 1137
1129 // We must set IsLoggingOut synchronously so that we can stop the packet loop reinvoking this method. 1138 if (!client.SceneAgent.IsChildAgent)
1130 client.IsLoggingOut = true; 1139 client.Kick("Simulator logged you out due to connection timeout");
1131 1140
1132 // Fire this out on a different thread so that we don't hold up outgoing packet processing for 1141 client.Close();
1133 // everybody else if this is being called due to an ack timeout.
1134 // This is the same as processing as the async process of a logout request.
1135 Util.FireAndForget(
1136 o =>
1137 { if (!client.SceneAgent.IsChildAgent)
1138 client.Kick("Simulator logged you out due to connection timeout");
1139 client.Close(); });
1140 } 1142 }
1141 1143
1142 private void IncomingPacketHandler() 1144 private void IncomingPacketHandler()
@@ -1450,8 +1452,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1450 protected void LogoutHandler(IClientAPI client) 1452 protected void LogoutHandler(IClientAPI client)
1451 { 1453 {
1452 client.SendLogoutPacket(); 1454 client.SendLogoutPacket();
1455
1453 if (!client.IsLoggingOut) 1456 if (!client.IsLoggingOut)
1454 RemoveClient(client); 1457 {
1458 client.IsLoggingOut = true;
1459 client.Close();
1460 }
1455 } 1461 }
1456 } 1462 }
1457} \ No newline at end of file 1463} \ No newline at end of file