diff options
author | Melanie Thielker | 2014-06-21 00:39:55 +0200 |
---|---|---|
committer | Melanie Thielker | 2014-06-21 00:39:55 +0200 |
commit | 159fcbf150b7da0e229b29aa7b94793484543d12 (patch) | |
tree | b8c0ff3b4c758a3fba8315b556c923ef4c02a185 /OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |
parent | Merge commit '68c8633ba18f0a11cfc0ed04d1d0c7c59e6cec76' (diff) | |
parent | Merge branch 'master' into careminster (diff) | |
download | opensim-SC-159fcbf150b7da0e229b29aa7b94793484543d12.zip opensim-SC-159fcbf150b7da0e229b29aa7b94793484543d12.tar.gz opensim-SC-159fcbf150b7da0e229b29aa7b94793484543d12.tar.bz2 opensim-SC-159fcbf150b7da0e229b29aa7b94793484543d12.tar.xz |
Merge branch 'master' of ssh://3dhosting.de/var/git/careminster
Conflicts:
OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 628 |
1 files changed, 545 insertions, 83 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 4154ef2..50dae2a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -34,6 +34,7 @@ using System.Net.Sockets; | |||
34 | using System.Reflection; | 34 | using System.Reflection; |
35 | using System.Threading; | 35 | using System.Threading; |
36 | using log4net; | 36 | using log4net; |
37 | using NDesk.Options; | ||
37 | using Nini.Config; | 38 | using Nini.Config; |
38 | using OpenMetaverse.Packets; | 39 | using OpenMetaverse.Packets; |
39 | using OpenSim.Framework; | 40 | using OpenSim.Framework; |
@@ -62,20 +63,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
62 | m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager); | 63 | m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager); |
63 | } | 64 | } |
64 | 65 | ||
65 | public void NetworkStop() | ||
66 | { | ||
67 | m_udpServer.Stop(); | ||
68 | } | ||
69 | |||
70 | public void AddScene(IScene scene) | 66 | public void AddScene(IScene scene) |
71 | { | 67 | { |
72 | m_udpServer.AddScene(scene); | 68 | m_udpServer.AddScene(scene); |
73 | 69 | ||
74 | StatsManager.RegisterStat( | 70 | StatsManager.RegisterStat( |
75 | new Stat( | 71 | new Stat( |
72 | "ClientLogoutsDueToNoReceives", | ||
73 | "Number of times a client has been logged out because no packets were received before the timeout.", | ||
74 | "", | ||
75 | "", | ||
76 | "clientstack", | ||
77 | scene.Name, | ||
78 | StatType.Pull, | ||
79 | MeasuresOfInterest.None, | ||
80 | stat => stat.Value = m_udpServer.ClientLogoutsDueToNoReceives, | ||
81 | StatVerbosity.Debug)); | ||
82 | |||
83 | StatsManager.RegisterStat( | ||
84 | new Stat( | ||
85 | "IncomingUDPReceivesCount", | ||
86 | "Number of UDP receives performed", | ||
87 | "", | ||
88 | "", | ||
89 | "clientstack", | ||
90 | scene.Name, | ||
91 | StatType.Pull, | ||
92 | MeasuresOfInterest.AverageChangeOverTime, | ||
93 | stat => stat.Value = m_udpServer.UdpReceives, | ||
94 | StatVerbosity.Debug)); | ||
95 | |||
96 | StatsManager.RegisterStat( | ||
97 | new Stat( | ||
76 | "IncomingPacketsProcessedCount", | 98 | "IncomingPacketsProcessedCount", |
77 | "Number of inbound UDP packets processed", | 99 | "Number of inbound LL protocol packets processed", |
78 | "Number of inbound UDP packets processed", | 100 | "", |
79 | "", | 101 | "", |
80 | "clientstack", | 102 | "clientstack", |
81 | scene.Name, | 103 | scene.Name, |
@@ -83,6 +105,86 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
83 | MeasuresOfInterest.AverageChangeOverTime, | 105 | MeasuresOfInterest.AverageChangeOverTime, |
84 | stat => stat.Value = m_udpServer.IncomingPacketsProcessed, | 106 | stat => stat.Value = m_udpServer.IncomingPacketsProcessed, |
85 | StatVerbosity.Debug)); | 107 | StatVerbosity.Debug)); |
108 | |||
109 | StatsManager.RegisterStat( | ||
110 | new Stat( | ||
111 | "IncomingPacketsMalformedCount", | ||
112 | "Number of inbound UDP packets that could not be recognized as LL protocol packets.", | ||
113 | "", | ||
114 | "", | ||
115 | "clientstack", | ||
116 | scene.Name, | ||
117 | StatType.Pull, | ||
118 | MeasuresOfInterest.AverageChangeOverTime, | ||
119 | stat => stat.Value = m_udpServer.IncomingMalformedPacketCount, | ||
120 | StatVerbosity.Info)); | ||
121 | |||
122 | StatsManager.RegisterStat( | ||
123 | new Stat( | ||
124 | "IncomingPacketsOrphanedCount", | ||
125 | "Number of inbound packets that were not initial connections packets and could not be associated with a viewer.", | ||
126 | "", | ||
127 | "", | ||
128 | "clientstack", | ||
129 | scene.Name, | ||
130 | StatType.Pull, | ||
131 | MeasuresOfInterest.AverageChangeOverTime, | ||
132 | stat => stat.Value = m_udpServer.IncomingOrphanedPacketCount, | ||
133 | StatVerbosity.Info)); | ||
134 | |||
135 | StatsManager.RegisterStat( | ||
136 | new Stat( | ||
137 | "IncomingPacketsResentCount", | ||
138 | "Number of inbound packets that clients indicate are resends.", | ||
139 | "", | ||
140 | "", | ||
141 | "clientstack", | ||
142 | scene.Name, | ||
143 | StatType.Pull, | ||
144 | MeasuresOfInterest.AverageChangeOverTime, | ||
145 | stat => stat.Value = m_udpServer.IncomingPacketsResentCount, | ||
146 | StatVerbosity.Debug)); | ||
147 | |||
148 | StatsManager.RegisterStat( | ||
149 | new Stat( | ||
150 | "OutgoingUDPSendsCount", | ||
151 | "Number of UDP sends performed", | ||
152 | "", | ||
153 | "", | ||
154 | "clientstack", | ||
155 | scene.Name, | ||
156 | StatType.Pull, | ||
157 | MeasuresOfInterest.AverageChangeOverTime, | ||
158 | stat => stat.Value = m_udpServer.UdpSends, | ||
159 | StatVerbosity.Debug)); | ||
160 | |||
161 | StatsManager.RegisterStat( | ||
162 | new Stat( | ||
163 | "OutgoingPacketsResentCount", | ||
164 | "Number of packets resent because a client did not acknowledge receipt", | ||
165 | "", | ||
166 | "", | ||
167 | "clientstack", | ||
168 | scene.Name, | ||
169 | StatType.Pull, | ||
170 | MeasuresOfInterest.AverageChangeOverTime, | ||
171 | stat => stat.Value = m_udpServer.PacketsResentCount, | ||
172 | StatVerbosity.Debug)); | ||
173 | |||
174 | StatsManager.RegisterStat( | ||
175 | new Stat( | ||
176 | "AverageUDPProcessTime", | ||
177 | "Average number of milliseconds taken to process each incoming UDP packet in a sample.", | ||
178 | "This is for initial receive processing which is separate from the later client LL packet processing stage.", | ||
179 | "ms", | ||
180 | "clientstack", | ||
181 | scene.Name, | ||
182 | StatType.Pull, | ||
183 | MeasuresOfInterest.None, | ||
184 | stat => stat.Value = m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond, | ||
185 | // stat => | ||
186 | // stat.Value = Math.Round(m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond, 7), | ||
187 | StatVerbosity.Debug)); | ||
86 | } | 188 | } |
87 | 189 | ||
88 | public bool HandlesRegion(Location x) | 190 | public bool HandlesRegion(Location x) |
@@ -107,10 +209,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
107 | /// </summary> | 209 | /// </summary> |
108 | public class LLUDPServer : OpenSimUDPBase | 210 | public class LLUDPServer : OpenSimUDPBase |
109 | { | 211 | { |
212 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
213 | |||
110 | /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> | 214 | /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> |
111 | public const int MTU = 1400; | 215 | public const int MTU = 1400; |
112 | 216 | ||
113 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 217 | /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary> |
218 | public int ClientLogoutsDueToNoReceives { get; private set; } | ||
219 | |||
220 | /// <summary> | ||
221 | /// Default packet debug level given to new clients | ||
222 | /// </summary> | ||
223 | public int DefaultClientPacketDebugLevel { get; set; } | ||
114 | 224 | ||
115 | /// <summary>The measured resolution of Environment.TickCount</summary> | 225 | /// <summary>The measured resolution of Environment.TickCount</summary> |
116 | public readonly float TickCountResolution; | 226 | public readonly float TickCountResolution; |
@@ -184,6 +294,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
184 | protected bool m_sendPing; | 294 | protected bool m_sendPing; |
185 | 295 | ||
186 | private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); | 296 | private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); |
297 | |||
298 | /// <summary> | ||
299 | /// Event used to signal when queued packets are available for sending. | ||
300 | /// </summary> | ||
301 | /// <remarks> | ||
302 | /// This allows the outbound loop to only operate when there is data to send rather than continuously polling. | ||
303 | /// Some data is sent immediately and not queued. That data would not trigger this event. | ||
304 | /// </remarks> | ||
305 | private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false); | ||
306 | |||
187 | private Pool<IncomingPacket> m_incomingPacketPool; | 307 | private Pool<IncomingPacket> m_incomingPacketPool; |
188 | 308 | ||
189 | /// <summary> | 309 | /// <summary> |
@@ -204,7 +324,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
204 | 324 | ||
205 | public Socket Server { get { return null; } } | 325 | public Socket Server { get { return null; } } |
206 | 326 | ||
207 | private int m_malformedCount = 0; // Guard against a spamming attack | 327 | /// <summary> |
328 | /// Record how many packets have been resent | ||
329 | /// </summary> | ||
330 | internal int PacketsResentCount { get; set; } | ||
331 | |||
332 | /// <summary> | ||
333 | /// Record how many packets have been sent | ||
334 | /// </summary> | ||
335 | internal int PacketsSentCount { get; set; } | ||
336 | |||
337 | /// <summary> | ||
338 | /// Record how many incoming packets are indicated as resends by clients. | ||
339 | /// </summary> | ||
340 | internal int IncomingPacketsResentCount { get; set; } | ||
341 | |||
342 | /// <summary> | ||
343 | /// Record how many inbound packets could not be recognized as LLUDP packets. | ||
344 | /// </summary> | ||
345 | public int IncomingMalformedPacketCount { get; private set; } | ||
346 | |||
347 | /// <summary> | ||
348 | /// Record how many inbound packets could not be associated with a simulator circuit. | ||
349 | /// </summary> | ||
350 | public int IncomingOrphanedPacketCount { get; private set; } | ||
208 | 351 | ||
209 | /// <summary> | 352 | /// <summary> |
210 | /// Record current outgoing client for monitoring purposes. | 353 | /// Record current outgoing client for monitoring purposes. |
@@ -461,6 +604,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
461 | m_scene = (Scene)scene; | 604 | m_scene = (Scene)scene; |
462 | m_location = new Location(m_scene.RegionInfo.RegionHandle); | 605 | m_location = new Location(m_scene.RegionInfo.RegionHandle); |
463 | 606 | ||
607 | StatsManager.RegisterStat( | ||
608 | new Stat( | ||
609 | "InboxPacketsCount", | ||
610 | "Number of LL protocol packets waiting for the second stage of processing after initial receive.", | ||
611 | "Number of LL protocol packets waiting for the second stage of processing after initial receive.", | ||
612 | "", | ||
613 | "clientstack", | ||
614 | scene.Name, | ||
615 | StatType.Pull, | ||
616 | MeasuresOfInterest.AverageChangeOverTime, | ||
617 | stat => stat.Value = packetInbox.Count, | ||
618 | StatVerbosity.Debug)); | ||
619 | |||
464 | // XXX: These stats are also pool stats but we register them separately since they are currently not | 620 | // XXX: These stats are also pool stats but we register them separately since they are currently not |
465 | // turned on and off by EnablePools()/DisablePools() | 621 | // turned on and off by EnablePools()/DisablePools() |
466 | StatsManager.RegisterStat( | 622 | StatsManager.RegisterStat( |
@@ -521,6 +677,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
521 | EnablePoolStats(); | 677 | EnablePoolStats(); |
522 | 678 | ||
523 | MainConsole.Instance.Commands.AddCommand( | 679 | MainConsole.Instance.Commands.AddCommand( |
680 | "Debug", false, "debug lludp packet", | ||
681 | "debug lludp packet [--default] <level> [<avatar-first-name> <avatar-last-name>]", | ||
682 | "Turn on packet debugging", | ||
683 | "If level > 255 then all incoming and outgoing packets are logged.\n" | ||
684 | + "If level <= 255 then incoming AgentUpdate and outgoing SimStats and SimulatorViewerTimeMessage packets are not logged.\n" | ||
685 | + "If level <= 200 then incoming RequestImage and outgoing ImagePacket, ImageData, LayerData and CoarseLocationUpdate packets are not logged.\n" | ||
686 | + "If level <= 100 then incoming ViewerEffect and AgentAnimation and outgoing ViewerEffect and AvatarAnimation packets are not logged.\n" | ||
687 | + "If level <= 50 then outgoing ImprovedTerseObjectUpdate packets are not logged.\n" | ||
688 | + "If level <= 0 then no packets are logged.\n" | ||
689 | + "If --default is specified then the level becomes the default logging level for all subsequent agents.\n" | ||
690 | + "In this case, you cannot also specify an avatar name.\n" | ||
691 | + "If an avatar name is given then only packets from that avatar are logged.", | ||
692 | HandlePacketCommand); | ||
693 | |||
694 | MainConsole.Instance.Commands.AddCommand( | ||
524 | "Debug", | 695 | "Debug", |
525 | false, | 696 | false, |
526 | "debug lludp start", | 697 | "debug lludp start", |
@@ -559,10 +730,78 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
559 | "debug lludp status", | 730 | "debug lludp status", |
560 | "Return status of LLUDP packet processing.", | 731 | "Return status of LLUDP packet processing.", |
561 | HandleStatusCommand); | 732 | HandleStatusCommand); |
733 | |||
734 | MainConsole.Instance.Commands.AddCommand( | ||
735 | "Debug", | ||
736 | false, | ||
737 | "debug lludp toggle agentupdate", | ||
738 | "debug lludp toggle agentupdate", | ||
739 | "Toggle whether agentupdate packets are processed or simply discarded.", | ||
740 | HandleAgentUpdateCommand); | ||
741 | } | ||
742 | |||
743 | private void HandlePacketCommand(string module, string[] args) | ||
744 | { | ||
745 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | ||
746 | return; | ||
747 | |||
748 | bool setAsDefaultLevel = false; | ||
749 | OptionSet optionSet = new OptionSet().Add("default", o => setAsDefaultLevel = o != null); | ||
750 | List<string> filteredArgs = optionSet.Parse(args); | ||
751 | |||
752 | string name = null; | ||
753 | |||
754 | if (filteredArgs.Count == 6) | ||
755 | { | ||
756 | if (!setAsDefaultLevel) | ||
757 | { | ||
758 | name = string.Format("{0} {1}", filteredArgs[4], filteredArgs[5]); | ||
759 | } | ||
760 | else | ||
761 | { | ||
762 | MainConsole.Instance.OutputFormat("ERROR: Cannot specify a user name when setting default logging level"); | ||
763 | return; | ||
764 | } | ||
765 | } | ||
766 | |||
767 | if (filteredArgs.Count > 3) | ||
768 | { | ||
769 | int newDebug; | ||
770 | if (int.TryParse(filteredArgs[3], out newDebug)) | ||
771 | { | ||
772 | if (setAsDefaultLevel) | ||
773 | { | ||
774 | DefaultClientPacketDebugLevel = newDebug; | ||
775 | MainConsole.Instance.OutputFormat( | ||
776 | "Debug packet debug for new clients set to {0} in {1}", DefaultClientPacketDebugLevel, m_scene.Name); | ||
777 | } | ||
778 | else | ||
779 | { | ||
780 | m_scene.ForEachScenePresence(sp => | ||
781 | { | ||
782 | if (name == null || sp.Name == name) | ||
783 | { | ||
784 | MainConsole.Instance.OutputFormat( | ||
785 | "Packet debug for {0} ({1}) set to {2} in {3}", | ||
786 | sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, m_scene.Name); | ||
787 | |||
788 | sp.ControllingClient.DebugPacketLevel = newDebug; | ||
789 | } | ||
790 | }); | ||
791 | } | ||
792 | } | ||
793 | else | ||
794 | { | ||
795 | MainConsole.Instance.Output("Usage: debug lludp packet [--default] 0..255 [<first-name> <last-name>]"); | ||
796 | } | ||
797 | } | ||
562 | } | 798 | } |
563 | 799 | ||
564 | private void HandleStartCommand(string module, string[] args) | 800 | private void HandleStartCommand(string module, string[] args) |
565 | { | 801 | { |
802 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | ||
803 | return; | ||
804 | |||
566 | if (args.Length != 4) | 805 | if (args.Length != 4) |
567 | { | 806 | { |
568 | MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>"); | 807 | MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>"); |
@@ -580,6 +819,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
580 | 819 | ||
581 | private void HandleStopCommand(string module, string[] args) | 820 | private void HandleStopCommand(string module, string[] args) |
582 | { | 821 | { |
822 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | ||
823 | return; | ||
824 | |||
583 | if (args.Length != 4) | 825 | if (args.Length != 4) |
584 | { | 826 | { |
585 | MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>"); | 827 | MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>"); |
@@ -597,6 +839,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
597 | 839 | ||
598 | private void HandlePoolCommand(string module, string[] args) | 840 | private void HandlePoolCommand(string module, string[] args) |
599 | { | 841 | { |
842 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | ||
843 | return; | ||
844 | |||
600 | if (args.Length != 4) | 845 | if (args.Length != 4) |
601 | { | 846 | { |
602 | MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); | 847 | MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); |
@@ -627,8 +872,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
627 | } | 872 | } |
628 | } | 873 | } |
629 | 874 | ||
875 | bool m_discardAgentUpdates; | ||
876 | |||
877 | private void HandleAgentUpdateCommand(string module, string[] args) | ||
878 | { | ||
879 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | ||
880 | return; | ||
881 | |||
882 | m_discardAgentUpdates = !m_discardAgentUpdates; | ||
883 | |||
884 | MainConsole.Instance.OutputFormat( | ||
885 | "Discard AgentUpdates now {0} for {1}", m_discardAgentUpdates, m_scene.Name); | ||
886 | } | ||
887 | |||
630 | private void HandleStatusCommand(string module, string[] args) | 888 | private void HandleStatusCommand(string module, string[] args) |
631 | { | 889 | { |
890 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | ||
891 | return; | ||
892 | |||
632 | MainConsole.Instance.OutputFormat( | 893 | MainConsole.Instance.OutputFormat( |
633 | "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); | 894 | "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); |
634 | 895 | ||
@@ -636,6 +897,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
636 | "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); | 897 | "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); |
637 | 898 | ||
638 | MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); | 899 | MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); |
900 | |||
901 | MainConsole.Instance.OutputFormat( | ||
902 | "Packet debug level for new clients is {0}", DefaultClientPacketDebugLevel); | ||
639 | } | 903 | } |
640 | 904 | ||
641 | public bool HandlesRegion(Location x) | 905 | public bool HandlesRegion(Location x) |
@@ -643,44 +907,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
643 | return x == m_location; | 907 | return x == m_location; |
644 | } | 908 | } |
645 | 909 | ||
646 | public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) | 910 | // public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) |
647 | { | 911 | // { |
648 | // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way | 912 | // // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way |
649 | if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting) | 913 | // if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting) |
650 | allowSplitting = false; | 914 | // allowSplitting = false; |
651 | 915 | // | |
652 | if (allowSplitting && packet.HasVariableBlocks) | 916 | // if (allowSplitting && packet.HasVariableBlocks) |
653 | { | 917 | // { |
654 | byte[][] datas = packet.ToBytesMultiple(); | 918 | // byte[][] datas = packet.ToBytesMultiple(); |
655 | int packetCount = datas.Length; | 919 | // int packetCount = datas.Length; |
656 | 920 | // | |
657 | if (packetCount < 1) | 921 | // if (packetCount < 1) |
658 | m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length); | 922 | // m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length); |
659 | 923 | // | |
660 | for (int i = 0; i < packetCount; i++) | 924 | // for (int i = 0; i < packetCount; i++) |
661 | { | 925 | // { |
662 | byte[] data = datas[i]; | 926 | // byte[] data = datas[i]; |
663 | m_scene.ForEachClient( | 927 | // m_scene.ForEachClient( |
664 | delegate(IClientAPI client) | 928 | // delegate(IClientAPI client) |
665 | { | 929 | // { |
666 | if (client is LLClientView) | 930 | // if (client is LLClientView) |
667 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); | 931 | // SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); |
668 | } | 932 | // } |
669 | ); | 933 | // ); |
670 | } | 934 | // } |
671 | } | 935 | // } |
672 | else | 936 | // else |
673 | { | 937 | // { |
674 | byte[] data = packet.ToBytes(); | 938 | // byte[] data = packet.ToBytes(); |
675 | m_scene.ForEachClient( | 939 | // m_scene.ForEachClient( |
676 | delegate(IClientAPI client) | 940 | // delegate(IClientAPI client) |
677 | { | 941 | // { |
678 | if (client is LLClientView) | 942 | // if (client is LLClientView) |
679 | SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); | 943 | // SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); |
680 | } | 944 | // } |
681 | ); | 945 | // ); |
682 | } | 946 | // } |
683 | } | 947 | // } |
684 | 948 | ||
685 | /// <summary> | 949 | /// <summary> |
686 | /// Start the process of sending a packet to the client. | 950 | /// Start the process of sending a packet to the client. |
@@ -700,6 +964,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
700 | if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) | 964 | if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) |
701 | allowSplitting = false; | 965 | allowSplitting = false; |
702 | 966 | ||
967 | bool packetQueued = false; | ||
968 | |||
703 | if (allowSplitting && packet.HasVariableBlocks) | 969 | if (allowSplitting && packet.HasVariableBlocks) |
704 | { | 970 | { |
705 | byte[][] datas = packet.ToBytesMultiple(); | 971 | byte[][] datas = packet.ToBytesMultiple(); |
@@ -711,16 +977,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
711 | for (int i = 0; i < packetCount; i++) | 977 | for (int i = 0; i < packetCount; i++) |
712 | { | 978 | { |
713 | byte[] data = datas[i]; | 979 | byte[] data = datas[i]; |
714 | SendPacketData(udpClient, data, packet.Type, category, method); | 980 | |
981 | if (!SendPacketData(udpClient, data, packet.Type, category, method)) | ||
982 | packetQueued = true; | ||
715 | } | 983 | } |
716 | } | 984 | } |
717 | else | 985 | else |
718 | { | 986 | { |
719 | byte[] data = packet.ToBytes(); | 987 | byte[] data = packet.ToBytes(); |
720 | SendPacketData(udpClient, data, packet.Type, category, method); | 988 | packetQueued = SendPacketData(udpClient, data, packet.Type, category, method); |
721 | } | 989 | } |
722 | 990 | ||
723 | PacketPool.Instance.ReturnPacket(packet); | 991 | PacketPool.Instance.ReturnPacket(packet); |
992 | |||
993 | if (packetQueued) | ||
994 | m_dataPresentEvent.Set(); | ||
724 | } | 995 | } |
725 | 996 | ||
726 | /// <summary> | 997 | /// <summary> |
@@ -734,7 +1005,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
734 | /// The method to call if the packet is not acked by the client. If null, then a standard | 1005 | /// The method to call if the packet is not acked by the client. If null, then a standard |
735 | /// resend of the packet is done. | 1006 | /// resend of the packet is done. |
736 | /// </param> | 1007 | /// </param> |
737 | public void SendPacketData( | 1008 | /// <returns>true if the data was sent immediately, false if it was queued for sending</returns> |
1009 | public bool SendPacketData( | ||
738 | LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method) | 1010 | LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method) |
739 | { | 1011 | { |
740 | int dataLength = data.Length; | 1012 | int dataLength = data.Length; |
@@ -807,7 +1079,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
807 | // packet so that it isn't sent before a queued update packet. | 1079 | // packet so that it isn't sent before a queued update packet. |
808 | bool requestQueue = type == PacketType.KillObject; | 1080 | bool requestQueue = type == PacketType.KillObject; |
809 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) | 1081 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) |
1082 | if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) | ||
1083 | { | ||
810 | SendPacketFinal(outgoingPacket); | 1084 | SendPacketFinal(outgoingPacket); |
1085 | return true; | ||
1086 | } | ||
1087 | |||
1088 | return false; | ||
811 | 1089 | ||
812 | #endregion Queue or Send | 1090 | #endregion Queue or Send |
813 | } | 1091 | } |
@@ -883,7 +1161,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
883 | // Fire this out on a different thread so that we don't hold up outgoing packet processing for | 1161 | // Fire this out on a different thread so that we don't hold up outgoing packet processing for |
884 | // everybody else if this is being called due to an ack timeout. | 1162 | // everybody else if this is being called due to an ack timeout. |
885 | // This is the same as processing as the async process of a logout request. | 1163 | // This is the same as processing as the async process of a logout request. |
886 | Util.FireAndForget(o => DeactivateClientDueToTimeout(client)); | 1164 | Util.FireAndForget(o => DeactivateClientDueToTimeout(client, timeoutTicks)); |
887 | 1165 | ||
888 | return; | 1166 | return; |
889 | } | 1167 | } |
@@ -988,6 +1266,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
988 | else | 1266 | else |
989 | { | 1267 | { |
990 | Interlocked.Increment(ref udpClient.PacketsResent); | 1268 | Interlocked.Increment(ref udpClient.PacketsResent); |
1269 | |||
1270 | // We're not going to worry about interlock yet since its not currently critical that this total count | ||
1271 | // is 100% correct | ||
1272 | PacketsResentCount++; | ||
991 | } | 1273 | } |
992 | 1274 | ||
993 | #endregion Sequence Number Assignment | 1275 | #endregion Sequence Number Assignment |
@@ -995,6 +1277,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
995 | // Stats tracking | 1277 | // Stats tracking |
996 | Interlocked.Increment(ref udpClient.PacketsSent); | 1278 | Interlocked.Increment(ref udpClient.PacketsSent); |
997 | 1279 | ||
1280 | // We're not going to worry about interlock yet since its not currently critical that this total count | ||
1281 | // is 100% correct | ||
1282 | PacketsSentCount++; | ||
1283 | |||
998 | // Put the UDP payload on the wire | 1284 | // Put the UDP payload on the wire |
999 | AsyncBeginSend(buffer); | 1285 | AsyncBeginSend(buffer); |
1000 | 1286 | ||
@@ -1002,6 +1288,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1002 | outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; | 1288 | outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; |
1003 | } | 1289 | } |
1004 | 1290 | ||
1291 | private void RecordMalformedInboundPacket(IPEndPoint endPoint) | ||
1292 | { | ||
1293 | // if (m_malformedCount < 100) | ||
1294 | // m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); | ||
1295 | |||
1296 | IncomingMalformedPacketCount++; | ||
1297 | |||
1298 | if ((IncomingMalformedPacketCount % 10000) == 0) | ||
1299 | m_log.WarnFormat( | ||
1300 | "[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack. Last was from {1}", | ||
1301 | IncomingMalformedPacketCount, endPoint); | ||
1302 | } | ||
1303 | |||
1005 | public override void PacketReceived(UDPPacketBuffer buffer) | 1304 | public override void PacketReceived(UDPPacketBuffer buffer) |
1006 | { | 1305 | { |
1007 | // Debugging/Profiling | 1306 | // Debugging/Profiling |
@@ -1023,6 +1322,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1023 | // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", | 1322 | // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", |
1024 | // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); | 1323 | // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); |
1025 | 1324 | ||
1325 | RecordMalformedInboundPacket(endPoint); | ||
1326 | |||
1026 | return; // Drop undersized packet | 1327 | return; // Drop undersized packet |
1027 | } | 1328 | } |
1028 | 1329 | ||
@@ -1041,6 +1342,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1041 | // "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}", | 1342 | // "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}", |
1042 | // buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); | 1343 | // buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); |
1043 | 1344 | ||
1345 | RecordMalformedInboundPacket(endPoint); | ||
1346 | |||
1044 | return; // Malformed header | 1347 | return; // Malformed header |
1045 | } | 1348 | } |
1046 | 1349 | ||
@@ -1056,34 +1359,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1056 | // Only allocate a buffer for zerodecoding if the packet is zerocoded | 1359 | // Only allocate a buffer for zerodecoding if the packet is zerocoded |
1057 | ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); | 1360 | ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); |
1058 | } | 1361 | } |
1059 | catch (MalformedDataException) | ||
1060 | { | ||
1061 | } | ||
1062 | catch (IndexOutOfRangeException) | ||
1063 | { | ||
1064 | // m_log.WarnFormat( | ||
1065 | // "[LLUDPSERVER]: Dropping short packet received from {0} in {1}", | ||
1066 | // buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); | ||
1067 | |||
1068 | return; // Drop short packet | ||
1069 | } | ||
1070 | catch (Exception e) | 1362 | catch (Exception e) |
1071 | { | 1363 | { |
1072 | if (m_malformedCount < 100) | 1364 | if (IncomingMalformedPacketCount < 100) |
1073 | m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); | 1365 | m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); |
1074 | |||
1075 | m_malformedCount++; | ||
1076 | |||
1077 | if ((m_malformedCount % 100000) == 0) | ||
1078 | m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); | ||
1079 | } | 1366 | } |
1080 | 1367 | ||
1081 | // Fail-safe check | 1368 | // Fail-safe check |
1082 | if (packet == null) | 1369 | if (packet == null) |
1083 | { | 1370 | { |
1084 | m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}:", | 1371 | if (IncomingMalformedPacketCount < 100) |
1085 | buffer.DataLength, buffer.RemoteEndPoint); | 1372 | { |
1086 | m_log.Error(Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); | 1373 | m_log.WarnFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}, data {2}:", |
1374 | buffer.DataLength, buffer.RemoteEndPoint, Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); | ||
1375 | } | ||
1376 | |||
1377 | RecordMalformedInboundPacket(endPoint); | ||
1378 | |||
1087 | return; | 1379 | return; |
1088 | } | 1380 | } |
1089 | 1381 | ||
@@ -1127,12 +1419,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1127 | queue.Enqueue(buffer); | 1419 | queue.Enqueue(buffer); |
1128 | return; | 1420 | return; |
1129 | } | 1421 | } |
1422 | else if (packet.Type == PacketType.CompleteAgentMovement) | ||
1423 | { | ||
1424 | // Send ack straight away to let the viewer know that we got it. | ||
1425 | SendAckImmediate(endPoint, packet.Header.Sequence); | ||
1426 | |||
1427 | // We need to copy the endpoint so that it doesn't get changed when another thread reuses the | ||
1428 | // buffer. | ||
1429 | object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; | ||
1430 | |||
1431 | Util.FireAndForget(HandleCompleteMovementIntoRegion, array); | ||
1432 | |||
1433 | return; | ||
1434 | } | ||
1130 | } | 1435 | } |
1131 | 1436 | ||
1132 | // Determine which agent this packet came from | 1437 | // Determine which agent this packet came from |
1133 | if (client == null || !(client is LLClientView)) | 1438 | if (client == null || !(client is LLClientView)) |
1134 | { | 1439 | { |
1135 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); | 1440 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); |
1441 | |||
1442 | IncomingOrphanedPacketCount++; | ||
1443 | |||
1444 | if ((IncomingOrphanedPacketCount % 10000) == 0) | ||
1445 | m_log.WarnFormat( | ||
1446 | "[LLUDPSERVER]: Received {0} orphaned packets so far. Last was from {1}", | ||
1447 | IncomingOrphanedPacketCount, endPoint); | ||
1448 | |||
1136 | return; | 1449 | return; |
1137 | } | 1450 | } |
1138 | 1451 | ||
@@ -1211,6 +1524,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1211 | 1524 | ||
1212 | #region Incoming Packet Accounting | 1525 | #region Incoming Packet Accounting |
1213 | 1526 | ||
1527 | // We're not going to worry about interlock yet since its not currently critical that this total count | ||
1528 | // is 100% correct | ||
1529 | if (packet.Header.Resent) | ||
1530 | IncomingPacketsResentCount++; | ||
1531 | |||
1214 | // Check the archive of received reliable packet IDs to see whether we already received this packet | 1532 | // Check the archive of received reliable packet IDs to see whether we already received this packet |
1215 | if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence)) | 1533 | if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence)) |
1216 | { | 1534 | { |
@@ -1233,6 +1551,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1233 | LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); | 1551 | LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); |
1234 | #endregion BinaryStats | 1552 | #endregion BinaryStats |
1235 | 1553 | ||
1554 | if (packet.Type == PacketType.AgentUpdate) | ||
1555 | { | ||
1556 | if (m_discardAgentUpdates) | ||
1557 | return; | ||
1558 | |||
1559 | ((LLClientView)client).TotalAgentUpdates++; | ||
1560 | |||
1561 | AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; | ||
1562 | |||
1563 | LLClientView llClient = client as LLClientView; | ||
1564 | if (agentUpdate.AgentData.SessionID != client.SessionId | ||
1565 | || agentUpdate.AgentData.AgentID != client.AgentId | ||
1566 | || !(llClient == null || llClient.CheckAgentUpdateSignificance(agentUpdate.AgentData)) ) | ||
1567 | { | ||
1568 | PacketPool.Instance.ReturnPacket(packet); | ||
1569 | return; | ||
1570 | } | ||
1571 | } | ||
1572 | |||
1236 | #region Ping Check Handling | 1573 | #region Ping Check Handling |
1237 | 1574 | ||
1238 | if (packet.Type == PacketType.StartPingCheck) | 1575 | if (packet.Type == PacketType.StartPingCheck) |
@@ -1421,7 +1758,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1421 | 1758 | ||
1422 | // We only want to send initial data to new clients, not ones which are being converted from child to root. | 1759 | // We only want to send initial data to new clients, not ones which are being converted from child to root. |
1423 | if (client != null) | 1760 | if (client != null) |
1424 | client.SceneAgent.SendInitialDataToMe(); | 1761 | { |
1762 | AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code); | ||
1763 | bool tp = (aCircuit.teleportFlags > 0); | ||
1764 | // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from | ||
1765 | if (!tp) | ||
1766 | client.SceneAgent.SendInitialDataToMe(); | ||
1767 | } | ||
1425 | 1768 | ||
1426 | // Now we know we can handle more data | 1769 | // Now we know we can handle more data |
1427 | Thread.Sleep(200); | 1770 | Thread.Sleep(200); |
@@ -1476,6 +1819,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1476 | } | 1819 | } |
1477 | } | 1820 | } |
1478 | 1821 | ||
1822 | private void HandleCompleteMovementIntoRegion(object o) | ||
1823 | { | ||
1824 | IPEndPoint endPoint = null; | ||
1825 | IClientAPI client = null; | ||
1826 | |||
1827 | try | ||
1828 | { | ||
1829 | object[] array = (object[])o; | ||
1830 | endPoint = (IPEndPoint)array[0]; | ||
1831 | CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1]; | ||
1832 | |||
1833 | m_log.DebugFormat( | ||
1834 | "[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, m_scene.Name); | ||
1835 | |||
1836 | // Determine which agent this packet came from | ||
1837 | // We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination | ||
1838 | // simulator with no existing child presence, the viewer (at least LL 3.3.4) will send UseCircuitCode | ||
1839 | // and then CompleteAgentMovement immediately without waiting for an ack. As we are now handling these | ||
1840 | // packets asynchronously, we need to account for this thread proceeding more quickly than the | ||
1841 | // UseCircuitCode thread. | ||
1842 | int count = 40; | ||
1843 | while (count-- > 0) | ||
1844 | { | ||
1845 | if (m_scene.TryGetClient(endPoint, out client)) | ||
1846 | { | ||
1847 | if (!client.IsActive) | ||
1848 | { | ||
1849 | // This check exists to catch a condition where the client has been closed by another thread | ||
1850 | // but has not yet been removed from the client manager (and possibly a new connection has | ||
1851 | // not yet been established). | ||
1852 | m_log.DebugFormat( | ||
1853 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.", | ||
1854 | endPoint, client.Name, m_scene.Name); | ||
1855 | } | ||
1856 | else if (client.SceneAgent == null) | ||
1857 | { | ||
1858 | // This check exists to catch a condition where the new client has been added to the client | ||
1859 | // manager but the SceneAgent has not yet been set in Scene.AddNewAgent(). If we are too | ||
1860 | // eager, then the new ScenePresence may not have registered a listener for this messsage | ||
1861 | // before we try to process it. | ||
1862 | // XXX: A better long term fix may be to add the SceneAgent before the client is added to | ||
1863 | // the client manager | ||
1864 | m_log.DebugFormat( | ||
1865 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.", | ||
1866 | endPoint, client.Name, m_scene.Name); | ||
1867 | } | ||
1868 | else | ||
1869 | { | ||
1870 | break; | ||
1871 | } | ||
1872 | } | ||
1873 | else | ||
1874 | { | ||
1875 | m_log.DebugFormat( | ||
1876 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.", | ||
1877 | endPoint, m_scene.Name); | ||
1878 | } | ||
1879 | |||
1880 | Thread.Sleep(200); | ||
1881 | } | ||
1882 | |||
1883 | if (client == null) | ||
1884 | { | ||
1885 | m_log.DebugFormat( | ||
1886 | "[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.", | ||
1887 | endPoint, m_scene.Name); | ||
1888 | |||
1889 | return; | ||
1890 | } | ||
1891 | else if (!client.IsActive || client.SceneAgent == null) | ||
1892 | { | ||
1893 | // This check exists to catch a condition where the client has been closed by another thread | ||
1894 | // but has not yet been removed from the client manager. | ||
1895 | // The packet could be simply ignored but it is useful to know if this condition occurred for other debugging | ||
1896 | // purposes. | ||
1897 | m_log.DebugFormat( | ||
1898 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.", | ||
1899 | endPoint, client.Name, m_scene.Name); | ||
1900 | |||
1901 | return; | ||
1902 | } | ||
1903 | |||
1904 | IncomingPacket incomingPacket1; | ||
1905 | |||
1906 | // Inbox insertion | ||
1907 | if (UsePools) | ||
1908 | { | ||
1909 | incomingPacket1 = m_incomingPacketPool.GetObject(); | ||
1910 | incomingPacket1.Client = (LLClientView)client; | ||
1911 | incomingPacket1.Packet = packet; | ||
1912 | } | ||
1913 | else | ||
1914 | { | ||
1915 | incomingPacket1 = new IncomingPacket((LLClientView)client, packet); | ||
1916 | } | ||
1917 | |||
1918 | packetInbox.Enqueue(incomingPacket1); | ||
1919 | } | ||
1920 | catch (Exception e) | ||
1921 | { | ||
1922 | m_log.ErrorFormat( | ||
1923 | "[LLUDPSERVER]: CompleteAgentMovement handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", | ||
1924 | endPoint != null ? endPoint.ToString() : "n/a", | ||
1925 | client != null ? client.Name : "unknown", | ||
1926 | client != null ? client.AgentId.ToString() : "unknown", | ||
1927 | e.Message, | ||
1928 | e.StackTrace); | ||
1929 | } | ||
1930 | } | ||
1931 | |||
1479 | /// <summary> | 1932 | /// <summary> |
1480 | /// Send an ack immediately to the given endpoint. | 1933 | /// Send an ack immediately to the given endpoint. |
1481 | /// </summary> | 1934 | /// </summary> |
@@ -1544,6 +1997,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1544 | 1997 | ||
1545 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); | 1998 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); |
1546 | client.OnLogout += LogoutHandler; | 1999 | client.OnLogout += LogoutHandler; |
2000 | client.DebugPacketLevel = DefaultClientPacketDebugLevel; | ||
1547 | 2001 | ||
1548 | ((LLClientView)client).DisableFacelights = m_disableFacelights; | 2002 | ((LLClientView)client).DisableFacelights = m_disableFacelights; |
1549 | 2003 | ||
@@ -1562,21 +2016,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1562 | /// regular client pings. | 2016 | /// regular client pings. |
1563 | /// </remarks> | 2017 | /// </remarks> |
1564 | /// <param name='client'></param> | 2018 | /// <param name='client'></param> |
1565 | private void DeactivateClientDueToTimeout(LLClientView client) | 2019 | /// <param name='timeoutTicks'></param> |
2020 | private void DeactivateClientDueToTimeout(LLClientView client, int timeoutTicks) | ||
1566 | { | 2021 | { |
1567 | lock (client.CloseSyncLock) | 2022 | lock (client.CloseSyncLock) |
1568 | { | 2023 | { |
2024 | ClientLogoutsDueToNoReceives++; | ||
2025 | |||
1569 | m_log.WarnFormat( | 2026 | m_log.WarnFormat( |
1570 | "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", | 2027 | "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", |
1571 | client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); | 2028 | client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, m_scene.Name); |
1572 | |||
1573 | StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); | ||
1574 | 2029 | ||
1575 | if (!client.SceneAgent.IsChildAgent) | 2030 | if (!client.SceneAgent.IsChildAgent) |
1576 | client.Kick("Simulator logged you out due to connection timeout"); | 2031 | client.Kick("Simulator logged you out due to connection timeout."); |
1577 | |||
1578 | client.CloseWithoutChecks(true); | ||
1579 | } | 2032 | } |
2033 | |||
2034 | m_scene.CloseAgent(client.AgentId, true); | ||
1580 | } | 2035 | } |
1581 | 2036 | ||
1582 | private void IncomingPacketHandler() | 2037 | private void IncomingPacketHandler() |
@@ -1592,6 +2047,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1592 | { | 2047 | { |
1593 | IncomingPacket incomingPacket = null; | 2048 | IncomingPacket incomingPacket = null; |
1594 | 2049 | ||
2050 | /* | ||
1595 | // HACK: This is a test to try and rate limit packet handling on Mono. | 2051 | // HACK: This is a test to try and rate limit packet handling on Mono. |
1596 | // If it works, a more elegant solution can be devised | 2052 | // If it works, a more elegant solution can be devised |
1597 | if (Util.FireAndForgetCount() < 2) | 2053 | if (Util.FireAndForgetCount() < 2) |
@@ -1599,6 +2055,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1599 | //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping"); | 2055 | //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping"); |
1600 | Thread.Sleep(30); | 2056 | Thread.Sleep(30); |
1601 | } | 2057 | } |
2058 | */ | ||
1602 | 2059 | ||
1603 | if (packetInbox.Dequeue(100, ref incomingPacket)) | 2060 | if (packetInbox.Dequeue(100, ref incomingPacket)) |
1604 | { | 2061 | { |
@@ -1694,8 +2151,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1694 | 2151 | ||
1695 | // If nothing was sent, sleep for the minimum amount of time before a | 2152 | // If nothing was sent, sleep for the minimum amount of time before a |
1696 | // token bucket could get more tokens | 2153 | // token bucket could get more tokens |
2154 | //if (!m_packetSent) | ||
2155 | // Thread.Sleep((int)TickCountResolution); | ||
2156 | // | ||
2157 | // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with | ||
2158 | // modern mono it reduces CPU base load since there is no more continuous polling. | ||
1697 | if (!m_packetSent) | 2159 | if (!m_packetSent) |
1698 | Thread.Sleep((int)TickCountResolution); | 2160 | m_dataPresentEvent.WaitOne(100); |
1699 | 2161 | ||
1700 | Watchdog.UpdateThread(); | 2162 | Watchdog.UpdateThread(); |
1701 | } | 2163 | } |
@@ -1912,7 +2374,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1912 | if (!client.IsLoggingOut) | 2374 | if (!client.IsLoggingOut) |
1913 | { | 2375 | { |
1914 | client.IsLoggingOut = true; | 2376 | client.IsLoggingOut = true; |
1915 | client.Close(false, false); | 2377 | m_scene.CloseAgent(client.AgentId, false); |
1916 | } | 2378 | } |
1917 | } | 2379 | } |
1918 | } | 2380 | } |