aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-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