aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs436
1 files changed, 394 insertions, 42 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 4154ef2..ad3f715 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;
34using System.Reflection; 34using System.Reflection;
35using System.Threading; 35using System.Threading;
36using log4net; 36using log4net;
37using NDesk.Options;
37using Nini.Config; 38using Nini.Config;
38using OpenMetaverse.Packets; 39using OpenMetaverse.Packets;
39using OpenSim.Framework; 40using 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,60 @@ 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 "OutgoingUDPSendsCount",
138 "Number of UDP sends performed",
139 "",
140 "",
141 "clientstack",
142 scene.Name,
143 StatType.Pull,
144 MeasuresOfInterest.AverageChangeOverTime,
145 stat => stat.Value = m_udpServer.UdpSends,
146 StatVerbosity.Debug));
147
148 StatsManager.RegisterStat(
149 new Stat(
150 "AverageUDPProcessTime",
151 "Average number of milliseconds taken to process each incoming UDP packet in a sample.",
152 "This is for initial receive processing which is separate from the later client LL packet processing stage.",
153 "ms",
154 "clientstack",
155 scene.Name,
156 StatType.Pull,
157 MeasuresOfInterest.None,
158 stat => stat.Value = m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond,
159// stat =>
160// stat.Value = Math.Round(m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond, 7),
161 StatVerbosity.Debug));
86 } 162 }
87 163
88 public bool HandlesRegion(Location x) 164 public bool HandlesRegion(Location x)
@@ -107,10 +183,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
107 /// </summary> 183 /// </summary>
108 public class LLUDPServer : OpenSimUDPBase 184 public class LLUDPServer : OpenSimUDPBase
109 { 185 {
186 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
187
110 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> 188 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
111 public const int MTU = 1400; 189 public const int MTU = 1400;
112 190
113 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 191 /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary>
192 public int ClientLogoutsDueToNoReceives { get; private set; }
193
194 /// <summary>
195 /// Default packet debug level given to new clients
196 /// </summary>
197 public int DefaultClientPacketDebugLevel { get; set; }
114 198
115 /// <summary>The measured resolution of Environment.TickCount</summary> 199 /// <summary>The measured resolution of Environment.TickCount</summary>
116 public readonly float TickCountResolution; 200 public readonly float TickCountResolution;
@@ -184,6 +268,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
184 protected bool m_sendPing; 268 protected bool m_sendPing;
185 269
186 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 270 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
271
272 /// <summary>
273 /// Event used to signal when queued packets are available for sending.
274 /// </summary>
275 /// <remarks>
276 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling.
277 /// Some data is sent immediately and not queued. That data would not trigger this event.
278 /// </remarks>
279 private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false);
280
187 private Pool<IncomingPacket> m_incomingPacketPool; 281 private Pool<IncomingPacket> m_incomingPacketPool;
188 282
189 /// <summary> 283 /// <summary>
@@ -204,7 +298,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
204 298
205 public Socket Server { get { return null; } } 299 public Socket Server { get { return null; } }
206 300
207 private int m_malformedCount = 0; // Guard against a spamming attack 301 /// <summary>
302 /// Record how many inbound packets could not be recognized as LLUDP packets.
303 /// </summary>
304 public int IncomingMalformedPacketCount { get; private set; }
305
306 /// <summary>
307 /// Record how many inbound packets could not be associated with a simulator circuit.
308 /// </summary>
309 public int IncomingOrphanedPacketCount { get; private set; }
208 310
209 /// <summary> 311 /// <summary>
210 /// Record current outgoing client for monitoring purposes. 312 /// Record current outgoing client for monitoring purposes.
@@ -461,6 +563,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
461 m_scene = (Scene)scene; 563 m_scene = (Scene)scene;
462 m_location = new Location(m_scene.RegionInfo.RegionHandle); 564 m_location = new Location(m_scene.RegionInfo.RegionHandle);
463 565
566 StatsManager.RegisterStat(
567 new Stat(
568 "InboxPacketsCount",
569 "Number of LL protocol packets waiting for the second stage of processing after initial receive.",
570 "Number of LL protocol packets waiting for the second stage of processing after initial receive.",
571 "",
572 "clientstack",
573 scene.Name,
574 StatType.Pull,
575 MeasuresOfInterest.AverageChangeOverTime,
576 stat => stat.Value = packetInbox.Count,
577 StatVerbosity.Debug));
578
464 // XXX: These stats are also pool stats but we register them separately since they are currently not 579 // 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() 580 // turned on and off by EnablePools()/DisablePools()
466 StatsManager.RegisterStat( 581 StatsManager.RegisterStat(
@@ -521,6 +636,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
521 EnablePoolStats(); 636 EnablePoolStats();
522 637
523 MainConsole.Instance.Commands.AddCommand( 638 MainConsole.Instance.Commands.AddCommand(
639 "Debug", false, "debug lludp packet",
640 "debug lludp packet [--default] <level> [<avatar-first-name> <avatar-last-name>]",
641 "Turn on packet debugging",
642 "If level > 255 then all incoming and outgoing packets are logged.\n"
643 + "If level <= 255 then incoming AgentUpdate and outgoing SimStats and SimulatorViewerTimeMessage packets are not logged.\n"
644 + "If level <= 200 then incoming RequestImage and outgoing ImagePacket, ImageData, LayerData and CoarseLocationUpdate packets are not logged.\n"
645 + "If level <= 100 then incoming ViewerEffect and AgentAnimation and outgoing ViewerEffect and AvatarAnimation packets are not logged.\n"
646 + "If level <= 50 then outgoing ImprovedTerseObjectUpdate packets are not logged.\n"
647 + "If level <= 0 then no packets are logged.\n"
648 + "If --default is specified then the level becomes the default logging level for all subsequent agents.\n"
649 + "In this case, you cannot also specify an avatar name.\n"
650 + "If an avatar name is given then only packets from that avatar are logged.",
651 HandlePacketCommand);
652
653 MainConsole.Instance.Commands.AddCommand(
524 "Debug", 654 "Debug",
525 false, 655 false,
526 "debug lludp start", 656 "debug lludp start",
@@ -559,10 +689,78 @@ namespace OpenSim.Region.ClientStack.LindenUDP
559 "debug lludp status", 689 "debug lludp status",
560 "Return status of LLUDP packet processing.", 690 "Return status of LLUDP packet processing.",
561 HandleStatusCommand); 691 HandleStatusCommand);
692
693 MainConsole.Instance.Commands.AddCommand(
694 "Debug",
695 false,
696 "debug lludp toggle agentupdate",
697 "debug lludp toggle agentupdate",
698 "Toggle whether agentupdate packets are processed or simply discarded.",
699 HandleAgentUpdateCommand);
700 }
701
702 private void HandlePacketCommand(string module, string[] args)
703 {
704 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
705 return;
706
707 bool setAsDefaultLevel = false;
708 OptionSet optionSet = new OptionSet().Add("default", o => setAsDefaultLevel = o != null);
709 List<string> filteredArgs = optionSet.Parse(args);
710
711 string name = null;
712
713 if (filteredArgs.Count == 6)
714 {
715 if (!setAsDefaultLevel)
716 {
717 name = string.Format("{0} {1}", filteredArgs[4], filteredArgs[5]);
718 }
719 else
720 {
721 MainConsole.Instance.OutputFormat("ERROR: Cannot specify a user name when setting default logging level");
722 return;
723 }
724 }
725
726 if (filteredArgs.Count > 3)
727 {
728 int newDebug;
729 if (int.TryParse(filteredArgs[3], out newDebug))
730 {
731 if (setAsDefaultLevel)
732 {
733 DefaultClientPacketDebugLevel = newDebug;
734 MainConsole.Instance.OutputFormat(
735 "Debug packet debug for new clients set to {0} in {1}", DefaultClientPacketDebugLevel, m_scene.Name);
736 }
737 else
738 {
739 m_scene.ForEachScenePresence(sp =>
740 {
741 if (name == null || sp.Name == name)
742 {
743 MainConsole.Instance.OutputFormat(
744 "Packet debug for {0} ({1}) set to {2} in {3}",
745 sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, m_scene.Name);
746
747 sp.ControllingClient.DebugPacketLevel = newDebug;
748 }
749 });
750 }
751 }
752 else
753 {
754 MainConsole.Instance.Output("Usage: debug lludp packet [--default] 0..255 [<first-name> <last-name>]");
755 }
756 }
562 } 757 }
563 758
564 private void HandleStartCommand(string module, string[] args) 759 private void HandleStartCommand(string module, string[] args)
565 { 760 {
761 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
762 return;
763
566 if (args.Length != 4) 764 if (args.Length != 4)
567 { 765 {
568 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>"); 766 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
@@ -580,6 +778,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
580 778
581 private void HandleStopCommand(string module, string[] args) 779 private void HandleStopCommand(string module, string[] args)
582 { 780 {
781 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
782 return;
783
583 if (args.Length != 4) 784 if (args.Length != 4)
584 { 785 {
585 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>"); 786 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>");
@@ -597,6 +798,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
597 798
598 private void HandlePoolCommand(string module, string[] args) 799 private void HandlePoolCommand(string module, string[] args)
599 { 800 {
801 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
802 return;
803
600 if (args.Length != 4) 804 if (args.Length != 4)
601 { 805 {
602 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); 806 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
@@ -627,8 +831,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
627 } 831 }
628 } 832 }
629 833
834 bool m_discardAgentUpdates;
835
836 private void HandleAgentUpdateCommand(string module, string[] args)
837 {
838 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
839 return;
840
841 m_discardAgentUpdates = !m_discardAgentUpdates;
842
843 MainConsole.Instance.OutputFormat(
844 "Discard AgentUpdates now {0} for {1}", m_discardAgentUpdates, m_scene.Name);
845 }
846
630 private void HandleStatusCommand(string module, string[] args) 847 private void HandleStatusCommand(string module, string[] args)
631 { 848 {
849 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
850 return;
851
632 MainConsole.Instance.OutputFormat( 852 MainConsole.Instance.OutputFormat(
633 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); 853 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
634 854
@@ -636,6 +856,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
636 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); 856 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
637 857
638 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); 858 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off");
859
860 MainConsole.Instance.OutputFormat(
861 "Packet debug level for new clients is {0}", DefaultClientPacketDebugLevel);
639 } 862 }
640 863
641 public bool HandlesRegion(Location x) 864 public bool HandlesRegion(Location x)
@@ -721,6 +944,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
721 } 944 }
722 945
723 PacketPool.Instance.ReturnPacket(packet); 946 PacketPool.Instance.ReturnPacket(packet);
947
948 m_dataPresentEvent.Set();
724 } 949 }
725 950
726 /// <summary> 951 /// <summary>
@@ -883,7 +1108,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 1108 // 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. 1109 // 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. 1110 // This is the same as processing as the async process of a logout request.
886 Util.FireAndForget(o => DeactivateClientDueToTimeout(client)); 1111 Util.FireAndForget(o => DeactivateClientDueToTimeout(client, timeoutTicks));
887 1112
888 return; 1113 return;
889 } 1114 }
@@ -1002,6 +1227,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1002 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; 1227 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
1003 } 1228 }
1004 1229
1230 private void RecordMalformedInboundPacket(IPEndPoint endPoint)
1231 {
1232// if (m_malformedCount < 100)
1233// m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
1234
1235 IncomingMalformedPacketCount++;
1236
1237 if ((IncomingMalformedPacketCount % 10000) == 0)
1238 m_log.WarnFormat(
1239 "[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack. Last was from {1}",
1240 IncomingMalformedPacketCount, endPoint);
1241 }
1242
1005 public override void PacketReceived(UDPPacketBuffer buffer) 1243 public override void PacketReceived(UDPPacketBuffer buffer)
1006 { 1244 {
1007 // Debugging/Profiling 1245 // Debugging/Profiling
@@ -1023,6 +1261,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1023// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", 1261// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
1024// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1262// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1025 1263
1264 RecordMalformedInboundPacket(endPoint);
1265
1026 return; // Drop undersized packet 1266 return; // Drop undersized packet
1027 } 1267 }
1028 1268
@@ -1041,6 +1281,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1041// "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}", 1281// "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}",
1042// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1282// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1043 1283
1284 RecordMalformedInboundPacket(endPoint);
1285
1044 return; // Malformed header 1286 return; // Malformed header
1045 } 1287 }
1046 1288
@@ -1056,34 +1298,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1056 // Only allocate a buffer for zerodecoding if the packet is zerocoded 1298 // Only allocate a buffer for zerodecoding if the packet is zerocoded
1057 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1299 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
1058 } 1300 }
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) 1301 catch (Exception e)
1071 { 1302 {
1072 if (m_malformedCount < 100) 1303 if (IncomingMalformedPacketCount < 100)
1073 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 1304 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 } 1305 }
1080 1306
1081 // Fail-safe check 1307 // Fail-safe check
1082 if (packet == null) 1308 if (packet == null)
1083 { 1309 {
1084 m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}:", 1310 if (IncomingMalformedPacketCount < 100)
1085 buffer.DataLength, buffer.RemoteEndPoint); 1311 {
1086 m_log.Error(Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); 1312 m_log.WarnFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}, data {2}:",
1313 buffer.DataLength, buffer.RemoteEndPoint, Utils.BytesToHexString(buffer.Data, buffer.DataLength, null));
1314 }
1315
1316 RecordMalformedInboundPacket(endPoint);
1317
1087 return; 1318 return;
1088 } 1319 }
1089 1320
@@ -1127,12 +1358,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1127 queue.Enqueue(buffer); 1358 queue.Enqueue(buffer);
1128 return; 1359 return;
1129 } 1360 }
1361 else if (packet.Type == PacketType.CompleteAgentMovement)
1362 {
1363 // Send ack straight away to let the viewer know that we got it.
1364 SendAckImmediate(endPoint, packet.Header.Sequence);
1365
1366 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1367 // buffer.
1368 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1369
1370 Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
1371
1372 return;
1373 }
1130 } 1374 }
1131 1375
1132 // Determine which agent this packet came from 1376 // Determine which agent this packet came from
1133 if (client == null || !(client is LLClientView)) 1377 if (client == null || !(client is LLClientView))
1134 { 1378 {
1135 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1379 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
1380
1381 IncomingOrphanedPacketCount++;
1382
1383 if ((IncomingOrphanedPacketCount % 10000) == 0)
1384 m_log.WarnFormat(
1385 "[LLUDPSERVER]: Received {0} orphaned packets so far. Last was from {1}",
1386 IncomingOrphanedPacketCount, endPoint);
1387
1136 return; 1388 return;
1137 } 1389 }
1138 1390
@@ -1233,6 +1485,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1233 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1485 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1234 #endregion BinaryStats 1486 #endregion BinaryStats
1235 1487
1488 if (packet.Type == PacketType.AgentUpdate)
1489 {
1490 if (m_discardAgentUpdates)
1491 return;
1492
1493 ((LLClientView)client).TotalAgentUpdates++;
1494
1495 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
1496
1497 LLClientView llClient = client as LLClientView;
1498 if (agentUpdate.AgentData.SessionID != client.SessionId
1499 || agentUpdate.AgentData.AgentID != client.AgentId
1500 || !(llClient == null || llClient.CheckAgentUpdateSignificance(agentUpdate.AgentData)) )
1501 {
1502 PacketPool.Instance.ReturnPacket(packet);
1503 return;
1504 }
1505 }
1506
1236 #region Ping Check Handling 1507 #region Ping Check Handling
1237 1508
1238 if (packet.Type == PacketType.StartPingCheck) 1509 if (packet.Type == PacketType.StartPingCheck)
@@ -1421,7 +1692,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1421 1692
1422 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1693 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1423 if (client != null) 1694 if (client != null)
1424 client.SceneAgent.SendInitialDataToMe(); 1695 {
1696 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1697 bool tp = (aCircuit.teleportFlags > 0);
1698 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from
1699 if (!tp)
1700 client.SceneAgent.SendInitialDataToMe();
1701 }
1425 1702
1426 // Now we know we can handle more data 1703 // Now we know we can handle more data
1427 Thread.Sleep(200); 1704 Thread.Sleep(200);
@@ -1476,6 +1753,72 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1476 } 1753 }
1477 } 1754 }
1478 1755
1756 private void HandleCompleteMovementIntoRegion(object o)
1757 {
1758 IPEndPoint endPoint = null;
1759 IClientAPI client = null;
1760
1761 try
1762 {
1763 object[] array = (object[])o;
1764 endPoint = (IPEndPoint)array[0];
1765 CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1];
1766
1767 // Determine which agent this packet came from
1768 int count = 20;
1769 bool ready = false;
1770 while (!ready && count-- > 0)
1771 {
1772 if (m_scene.TryGetClient(endPoint, out client) && client.IsActive && client.SceneAgent != null)
1773 {
1774 LLClientView llClientView = (LLClientView)client;
1775 LLUDPClient udpClient = llClientView.UDPClient;
1776 if (udpClient != null && udpClient.IsConnected)
1777 ready = true;
1778 else
1779 {
1780 m_log.Debug("[LLUDPSERVER]: Received a CompleteMovementIntoRegion in " + m_scene.RegionInfo.RegionName + " (not ready yet)");
1781 Thread.Sleep(200);
1782 }
1783 }
1784 else
1785 {
1786 m_log.Debug("[LLUDPSERVER]: Received a CompleteMovementIntoRegion in " + m_scene.RegionInfo.RegionName + " (not ready yet)");
1787 Thread.Sleep(200);
1788 }
1789 }
1790
1791 if (client == null)
1792 return;
1793
1794 IncomingPacket incomingPacket1;
1795
1796 // Inbox insertion
1797 if (UsePools)
1798 {
1799 incomingPacket1 = m_incomingPacketPool.GetObject();
1800 incomingPacket1.Client = (LLClientView)client;
1801 incomingPacket1.Packet = packet;
1802 }
1803 else
1804 {
1805 incomingPacket1 = new IncomingPacket((LLClientView)client, packet);
1806 }
1807
1808 packetInbox.Enqueue(incomingPacket1);
1809 }
1810 catch (Exception e)
1811 {
1812 m_log.ErrorFormat(
1813 "[LLUDPSERVER]: CompleteMovementIntoRegion handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1814 endPoint != null ? endPoint.ToString() : "n/a",
1815 client != null ? client.Name : "unknown",
1816 client != null ? client.AgentId.ToString() : "unknown",
1817 e.Message,
1818 e.StackTrace);
1819 }
1820 }
1821
1479 /// <summary> 1822 /// <summary>
1480 /// Send an ack immediately to the given endpoint. 1823 /// Send an ack immediately to the given endpoint.
1481 /// </summary> 1824 /// </summary>
@@ -1544,6 +1887,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1544 1887
1545 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1888 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1546 client.OnLogout += LogoutHandler; 1889 client.OnLogout += LogoutHandler;
1890 client.DebugPacketLevel = DefaultClientPacketDebugLevel;
1547 1891
1548 ((LLClientView)client).DisableFacelights = m_disableFacelights; 1892 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1549 1893
@@ -1562,21 +1906,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1562 /// regular client pings. 1906 /// regular client pings.
1563 /// </remarks> 1907 /// </remarks>
1564 /// <param name='client'></param> 1908 /// <param name='client'></param>
1565 private void DeactivateClientDueToTimeout(LLClientView client) 1909 /// <param name='timeoutTicks'></param>
1910 private void DeactivateClientDueToTimeout(LLClientView client, int timeoutTicks)
1566 { 1911 {
1567 lock (client.CloseSyncLock) 1912 lock (client.CloseSyncLock)
1568 { 1913 {
1914 ClientLogoutsDueToNoReceives++;
1915
1569 m_log.WarnFormat( 1916 m_log.WarnFormat(
1570 "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", 1917 "[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); 1918 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, m_scene.Name);
1572
1573 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
1574 1919
1575 if (!client.SceneAgent.IsChildAgent) 1920 if (!client.SceneAgent.IsChildAgent)
1576 client.Kick("Simulator logged you out due to connection timeout"); 1921 client.Kick("Simulator logged you out due to connection timeout.");
1577
1578 client.CloseWithoutChecks(true);
1579 } 1922 }
1923
1924 m_scene.IncomingCloseAgent(client.AgentId, true);
1580 } 1925 }
1581 1926
1582 private void IncomingPacketHandler() 1927 private void IncomingPacketHandler()
@@ -1592,6 +1937,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1592 { 1937 {
1593 IncomingPacket incomingPacket = null; 1938 IncomingPacket incomingPacket = null;
1594 1939
1940 /*
1595 // HACK: This is a test to try and rate limit packet handling on Mono. 1941 // 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 1942 // If it works, a more elegant solution can be devised
1597 if (Util.FireAndForgetCount() < 2) 1943 if (Util.FireAndForgetCount() < 2)
@@ -1599,6 +1945,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1599 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping"); 1945 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping");
1600 Thread.Sleep(30); 1946 Thread.Sleep(30);
1601 } 1947 }
1948 */
1602 1949
1603 if (packetInbox.Dequeue(100, ref incomingPacket)) 1950 if (packetInbox.Dequeue(100, ref incomingPacket))
1604 { 1951 {
@@ -1694,8 +2041,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1694 2041
1695 // If nothing was sent, sleep for the minimum amount of time before a 2042 // If nothing was sent, sleep for the minimum amount of time before a
1696 // token bucket could get more tokens 2043 // token bucket could get more tokens
2044 //if (!m_packetSent)
2045 // Thread.Sleep((int)TickCountResolution);
2046 //
2047 // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with
2048 // modern mono it reduces CPU base load since there is no more continuous polling.
1697 if (!m_packetSent) 2049 if (!m_packetSent)
1698 Thread.Sleep((int)TickCountResolution); 2050 m_dataPresentEvent.WaitOne(100);
1699 2051
1700 Watchdog.UpdateThread(); 2052 Watchdog.UpdateThread();
1701 } 2053 }
@@ -1912,7 +2264,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1912 if (!client.IsLoggingOut) 2264 if (!client.IsLoggingOut)
1913 { 2265 {
1914 client.IsLoggingOut = true; 2266 client.IsLoggingOut = true;
1915 client.Close(false, false); 2267 m_scene.IncomingCloseAgent(client.AgentId, false);
1916 } 2268 }
1917 } 2269 }
1918 } 2270 }