diff options
-rw-r--r-- | OpenSim/Framework/IClientAPI.cs | 9 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 64 |
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 |