aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs974
1 files changed, 700 insertions, 274 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index a7628d2..4528714 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -40,8 +40,9 @@ using OpenSim.Framework;
40using OpenSim.Framework.Console; 40using OpenSim.Framework.Console;
41using OpenSim.Framework.Monitoring; 41using OpenSim.Framework.Monitoring;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Interfaces;
43using OpenMetaverse; 44using OpenMetaverse;
44 45using Mono.Addins;
45using TokenBucket = OpenSim.Region.ClientStack.LindenUDP.TokenBucket; 46using TokenBucket = OpenSim.Region.ClientStack.LindenUDP.TokenBucket;
46 47
47namespace OpenSim.Region.ClientStack.LindenUDP 48namespace OpenSim.Region.ClientStack.LindenUDP
@@ -49,22 +50,58 @@ namespace OpenSim.Region.ClientStack.LindenUDP
49 /// <summary> 50 /// <summary>
50 /// A shim around LLUDPServer that implements the IClientNetworkServer interface 51 /// A shim around LLUDPServer that implements the IClientNetworkServer interface
51 /// </summary> 52 /// </summary>
52 public sealed class LLUDPServerShim : IClientNetworkServer 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LLUDPServerShim")]
54 public sealed class LLUDPServerShim : INonSharedRegionModule
53 { 55 {
56 private bool m_Enabled = true;
57 private IConfigSource m_Config;
54 LLUDPServer m_udpServer; 58 LLUDPServer m_udpServer;
55 59
56 public LLUDPServerShim() 60 #region INonSharedRegionModule
61 public string Name
57 { 62 {
63 get { return "LLUDPServerShim"; }
58 } 64 }
59 65
60 public void Initialise(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 66 public Type ReplaceableInterface
61 { 67 {
62 m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager); 68 get { return null; }
63 } 69 }
64 70
65 public void NetworkStop() 71 public void Initialise(IConfigSource source)
66 { 72 {
67 m_udpServer.Stop(); 73 m_Config = source;
74 }
75
76 public void Close()
77 {
78 }
79
80 public void AddRegion(Scene scene)
81 {
82 uint port = (uint)scene.RegionInfo.InternalEndPoint.Port;
83
84 IPAddress listenIP = scene.RegionInfo.InternalEndPoint.Address;
85 Initialise(listenIP, ref port, scene.RegionInfo.ProxyOffset, scene.RegionInfo.m_allow_alternate_ports, m_Config, scene.AuthenticateHandler);
86 scene.RegionInfo.InternalEndPoint.Port = (int)port;
87
88 AddScene(scene);
89 }
90
91 public void RemoveRegion(Scene scene)
92 {
93 Stop();
94 }
95
96 public void RegionLoaded(Scene scene)
97 {
98 Start();
99 }
100 #endregion
101
102 public void Initialise(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
103 {
104 m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager);
68 } 105 }
69 106
70 public void AddScene(IScene scene) 107 public void AddScene(IScene scene)
@@ -73,9 +110,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
73 110
74 StatsManager.RegisterStat( 111 StatsManager.RegisterStat(
75 new Stat( 112 new Stat(
113 "ClientLogoutsDueToNoReceives",
114 "Number of times a client has been logged out because no packets were received before the timeout.",
115 "",
116 "",
117 "clientstack",
118 scene.Name,
119 StatType.Pull,
120 MeasuresOfInterest.None,
121 stat => stat.Value = m_udpServer.ClientLogoutsDueToNoReceives,
122 StatVerbosity.Debug));
123
124 StatsManager.RegisterStat(
125 new Stat(
126 "IncomingUDPReceivesCount",
127 "Number of UDP receives performed",
128 "",
129 "",
130 "clientstack",
131 scene.Name,
132 StatType.Pull,
133 MeasuresOfInterest.AverageChangeOverTime,
134 stat => stat.Value = m_udpServer.UdpReceives,
135 StatVerbosity.Debug));
136
137 StatsManager.RegisterStat(
138 new Stat(
76 "IncomingPacketsProcessedCount", 139 "IncomingPacketsProcessedCount",
77 "Number of inbound UDP packets processed", 140 "Number of inbound LL protocol packets processed",
78 "Number of inbound UDP packets processed", 141 "",
79 "", 142 "",
80 "clientstack", 143 "clientstack",
81 scene.Name, 144 scene.Name,
@@ -83,6 +146,86 @@ namespace OpenSim.Region.ClientStack.LindenUDP
83 MeasuresOfInterest.AverageChangeOverTime, 146 MeasuresOfInterest.AverageChangeOverTime,
84 stat => stat.Value = m_udpServer.IncomingPacketsProcessed, 147 stat => stat.Value = m_udpServer.IncomingPacketsProcessed,
85 StatVerbosity.Debug)); 148 StatVerbosity.Debug));
149
150 StatsManager.RegisterStat(
151 new Stat(
152 "IncomingPacketsMalformedCount",
153 "Number of inbound UDP packets that could not be recognized as LL protocol packets.",
154 "",
155 "",
156 "clientstack",
157 scene.Name,
158 StatType.Pull,
159 MeasuresOfInterest.AverageChangeOverTime,
160 stat => stat.Value = m_udpServer.IncomingMalformedPacketCount,
161 StatVerbosity.Info));
162
163 StatsManager.RegisterStat(
164 new Stat(
165 "IncomingPacketsOrphanedCount",
166 "Number of inbound packets that were not initial connections packets and could not be associated with a viewer.",
167 "",
168 "",
169 "clientstack",
170 scene.Name,
171 StatType.Pull,
172 MeasuresOfInterest.AverageChangeOverTime,
173 stat => stat.Value = m_udpServer.IncomingOrphanedPacketCount,
174 StatVerbosity.Info));
175
176 StatsManager.RegisterStat(
177 new Stat(
178 "IncomingPacketsResentCount",
179 "Number of inbound packets that clients indicate are resends.",
180 "",
181 "",
182 "clientstack",
183 scene.Name,
184 StatType.Pull,
185 MeasuresOfInterest.AverageChangeOverTime,
186 stat => stat.Value = m_udpServer.IncomingPacketsResentCount,
187 StatVerbosity.Debug));
188
189 StatsManager.RegisterStat(
190 new Stat(
191 "OutgoingUDPSendsCount",
192 "Number of UDP sends performed",
193 "",
194 "",
195 "clientstack",
196 scene.Name,
197 StatType.Pull,
198 MeasuresOfInterest.AverageChangeOverTime,
199 stat => stat.Value = m_udpServer.UdpSends,
200 StatVerbosity.Debug));
201
202 StatsManager.RegisterStat(
203 new Stat(
204 "OutgoingPacketsResentCount",
205 "Number of packets resent because a client did not acknowledge receipt",
206 "",
207 "",
208 "clientstack",
209 scene.Name,
210 StatType.Pull,
211 MeasuresOfInterest.AverageChangeOverTime,
212 stat => stat.Value = m_udpServer.PacketsResentCount,
213 StatVerbosity.Debug));
214
215 StatsManager.RegisterStat(
216 new Stat(
217 "AverageUDPProcessTime",
218 "Average number of milliseconds taken to process each incoming UDP packet in a sample.",
219 "This is for initial receive processing which is separate from the later client LL packet processing stage.",
220 "ms",
221 "clientstack",
222 scene.Name,
223 StatType.Pull,
224 MeasuresOfInterest.None,
225 stat => stat.Value = m_udpServer.AverageReceiveTicksForLastSamplePeriod,
226// stat =>
227// stat.Value = Math.Round(m_udpServer.AverageReceiveTicksForLastSamplePeriod, 7),
228 StatVerbosity.Debug));
86 } 229 }
87 230
88 public bool HandlesRegion(Location x) 231 public bool HandlesRegion(Location x)
@@ -99,6 +242,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
99 { 242 {
100 m_udpServer.Stop(); 243 m_udpServer.Stop();
101 } 244 }
245
102 } 246 }
103 247
104 /// <summary> 248 /// <summary>
@@ -107,10 +251,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
107 /// </summary> 251 /// </summary>
108 public class LLUDPServer : OpenSimUDPBase 252 public class LLUDPServer : OpenSimUDPBase
109 { 253 {
254 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
255
110 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> 256 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
111 public const int MTU = 1400; 257 public const int MTU = 1400;
112 258
113 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 259 /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary>
260 public int ClientLogoutsDueToNoReceives { get; private set; }
261
262 /// <summary>
263 /// Default packet debug level given to new clients
264 /// </summary>
265 public int DefaultClientPacketDebugLevel { get; set; }
266
267 /// <summary>
268 /// If set then all inbound agent updates are discarded. For debugging purposes.
269 /// discard agent update.
270 /// </summary>
271 public bool DiscardInboundAgentUpdates { get; set; }
114 272
115 /// <summary>The measured resolution of Environment.TickCount</summary> 273 /// <summary>The measured resolution of Environment.TickCount</summary>
116 public readonly float TickCountResolution; 274 public readonly float TickCountResolution;
@@ -128,19 +286,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
128 /// <summary>Incoming packets that are awaiting handling</summary> 286 /// <summary>Incoming packets that are awaiting handling</summary>
129 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 287 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
130 288
131 /// <summary></summary>
132 //private UDPClientCollection m_clients = new UDPClientCollection();
133 /// <summary>Bandwidth throttle for this UDP server</summary> 289 /// <summary>Bandwidth throttle for this UDP server</summary>
134 protected TokenBucket m_throttle; 290 public TokenBucket Throttle { get; private set; }
135 291
136 /// <summary>Bandwidth throttle rates for this UDP server</summary> 292 /// <summary>Per client throttle rates enforced by this server</summary>
293 /// <remarks>
294 /// If the total rate is non-zero, then this is the maximum total throttle setting that any client can ever have.
295 /// The other rates (resend, asset, etc.) are the defaults for a new client and can be changed (and usually
296 /// do get changed immediately). They do not need to sum to the total.
297 /// </remarks>
137 public ThrottleRates ThrottleRates { get; private set; } 298 public ThrottleRates ThrottleRates { get; private set; }
138 299
139 /// <summary>Manages authentication for agent circuits</summary> 300 /// <summary>Manages authentication for agent circuits</summary>
140 private AgentCircuitManager m_circuitManager; 301 private AgentCircuitManager m_circuitManager;
141 302
142 /// <summary>Reference to the scene this UDP server is attached to</summary> 303 /// <summary>Reference to the scene this UDP server is attached to</summary>
143 protected Scene m_scene; 304 public Scene Scene { get; private set; }
144 305
145 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 306 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
146 private Location m_location; 307 private Location m_location;
@@ -181,6 +342,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 /// <summary>Flag to signal when clients should send pings</summary> 342 /// <summary>Flag to signal when clients should send pings</summary>
182 protected bool m_sendPing; 343 protected bool m_sendPing;
183 344
345 /// <summary>
346 /// Event used to signal when queued packets are available for sending.
347 /// </summary>
348 /// <remarks>
349 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling.
350 /// Some data is sent immediately and not queued. That data would not trigger this event.
351 /// </remarks>
352 private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false);
353
184 private Pool<IncomingPacket> m_incomingPacketPool; 354 private Pool<IncomingPacket> m_incomingPacketPool;
185 355
186 /// <summary> 356 /// <summary>
@@ -201,7 +371,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
201 371
202 public Socket Server { get { return null; } } 372 public Socket Server { get { return null; } }
203 373
204 private int m_malformedCount = 0; // Guard against a spamming attack 374 /// <summary>
375 /// Record how many packets have been resent
376 /// </summary>
377 internal int PacketsResentCount { get; set; }
378
379 /// <summary>
380 /// Record how many packets have been sent
381 /// </summary>
382 internal int PacketsSentCount { get; set; }
383
384 /// <summary>
385 /// Record how many incoming packets are indicated as resends by clients.
386 /// </summary>
387 internal int IncomingPacketsResentCount { get; set; }
388
389 /// <summary>
390 /// Record how many inbound packets could not be recognized as LLUDP packets.
391 /// </summary>
392 public int IncomingMalformedPacketCount { get; private set; }
393
394 /// <summary>
395 /// Record how many inbound packets could not be associated with a simulator circuit.
396 /// </summary>
397 public int IncomingOrphanedPacketCount { get; private set; }
205 398
206 /// <summary> 399 /// <summary>
207 /// Record current outgoing client for monitoring purposes. 400 /// Record current outgoing client for monitoring purposes.
@@ -213,6 +406,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
213 /// </summary> 406 /// </summary>
214 private IClientAPI m_currentIncomingClient; 407 private IClientAPI m_currentIncomingClient;
215 408
409 /// <summary>
410 /// Queue some low priority but potentially high volume async requests so that they don't overwhelm available
411 /// threadpool threads.
412 /// </summary>
413 public JobEngine IpahEngine { get; private set; }
414
415 /// <summary>
416 /// Run queue empty processing within a single persistent thread.
417 /// </summary>
418 /// <remarks>
419 /// This is the alternative to having every
420 /// connection schedule its own job in the threadpool which causes performance problems when there are many
421 /// connections.
422 /// </remarks>
423 public JobEngine OqrEngine { get; private set; }
424
216 public LLUDPServer( 425 public LLUDPServer(
217 IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, 426 IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port,
218 IConfigSource configSource, AgentCircuitManager circuitManager) 427 IConfigSource configSource, AgentCircuitManager circuitManager)
@@ -278,27 +487,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
278 m_shouldCollectStats = false; 487 m_shouldCollectStats = false;
279 if (config != null) 488 if (config != null)
280 { 489 {
281 if (config.Contains("enabled") && config.GetBoolean("enabled")) 490 m_shouldCollectStats = config.GetBoolean("Enabled", false);
282 { 491 binStatsMaxFilesize = TimeSpan.FromSeconds(config.GetInt("packet_headers_period_seconds", 300));
283 if (config.Contains("collect_packet_headers")) 492 binStatsDir = config.GetString("stats_dir", ".");
284 m_shouldCollectStats = config.GetBoolean("collect_packet_headers"); 493 m_aggregatedBWStats = config.GetBoolean("aggregatedBWStats", false);
285 if (config.Contains("packet_headers_period_seconds")) 494 }
286 { 495 #endregion BinaryStats
287 binStatsMaxFilesize = TimeSpan.FromSeconds(config.GetInt("region_stats_period_seconds")); 496
288 } 497 // FIXME: Can't add info here because don't know scene yet.
289 if (config.Contains("stats_dir")) 498// m_throttle
290 { 499// = new TokenBucket(
291 binStatsDir = config.GetString("stats_dir"); 500// string.Format("server throttle bucket for {0}", Scene.Name), null, sceneThrottleBps);
292 } 501
293 } 502 Throttle = new TokenBucket("server throttle bucket", null, 0, sceneThrottleBps);
294 else 503
295 {
296 m_shouldCollectStats = false;
297 }
298 }
299 #endregion BinaryStats
300
301 m_throttle = new TokenBucket(null, sceneThrottleBps);
302 ThrottleRates = new ThrottleRates(configSource); 504 ThrottleRates = new ThrottleRates(configSource);
303 505
304 if (usePools) 506 if (usePools)
@@ -309,11 +511,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
309 { 511 {
310 StartInbound(); 512 StartInbound();
311 StartOutbound(); 513 StartOutbound();
514 IpahEngine.Start();
515 OqrEngine.Start();
312 516
313 m_elapsedMSSinceLastStatReport = Environment.TickCount; 517 m_elapsedMSSinceLastStatReport = Environment.TickCount;
314 } 518 }
315 519
316 private void StartInbound() 520 public void StartInbound()
317 { 521 {
318 m_log.InfoFormat( 522 m_log.InfoFormat(
319 "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", 523 "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}",
@@ -322,9 +526,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
322 base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); 526 base.StartInbound(m_recvBufferSize, m_asyncPacketHandling);
323 527
324 // This thread will process the packets received that are placed on the packetInbox 528 // This thread will process the packets received that are placed on the packetInbox
325 Watchdog.StartThread( 529 WorkManager.StartThread(
326 IncomingPacketHandler, 530 IncomingPacketHandler,
327 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), 531 string.Format("Incoming Packets ({0})", Scene.Name),
328 ThreadPriority.Normal, 532 ThreadPriority.Normal,
329 false, 533 false,
330 true, 534 true,
@@ -332,15 +536,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
332 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 536 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
333 } 537 }
334 538
335 private new void StartOutbound() 539 public override void StartOutbound()
336 { 540 {
337 m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); 541 m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server");
338 542
339 base.StartOutbound(); 543 base.StartOutbound();
340 544
341 Watchdog.StartThread( 545 WorkManager.StartThread(
342 OutgoingPacketHandler, 546 OutgoingPacketHandler,
343 string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName), 547 string.Format("Outgoing Packets ({0})", Scene.Name),
344 ThreadPriority.Normal, 548 ThreadPriority.Normal,
345 false, 549 false,
346 true, 550 true,
@@ -350,12 +554,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
350 554
351 public void Stop() 555 public void Stop()
352 { 556 {
353 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); 557 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + Scene.Name);
354 base.StopOutbound(); 558 base.StopOutbound();
355 base.StopInbound(); 559 base.StopInbound();
560 IpahEngine.Stop();
561 OqrEngine.Stop();
356 } 562 }
357 563
358 protected override bool EnablePools() 564 public override bool EnablePools()
359 { 565 {
360 if (!UsePools) 566 if (!UsePools)
361 { 567 {
@@ -369,7 +575,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
369 return false; 575 return false;
370 } 576 }
371 577
372 protected override bool DisablePools() 578 public override bool DisablePools()
373 { 579 {
374 if (UsePools) 580 if (UsePools)
375 { 581 {
@@ -389,7 +595,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
389 /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene 595 /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene
390 /// stats. 596 /// stats.
391 /// </summary> 597 /// </summary>
392 private void EnablePoolStats() 598 protected internal void EnablePoolStats()
393 { 599 {
394 m_poolCountStat 600 m_poolCountStat
395 = new Stat( 601 = new Stat(
@@ -398,7 +604,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
398 "The number of objects currently stored within the UDPPacketBuffer pool", 604 "The number of objects currently stored within the UDPPacketBuffer pool",
399 "", 605 "",
400 "clientstack", 606 "clientstack",
401 m_scene.Name, 607 Scene.Name,
402 StatType.Pull, 608 StatType.Pull,
403 stat => stat.Value = Pool.Count, 609 stat => stat.Value = Pool.Count,
404 StatVerbosity.Debug); 610 StatVerbosity.Debug);
@@ -412,7 +618,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
412 "The number of objects currently stored within the incoming packet pool", 618 "The number of objects currently stored within the incoming packet pool",
413 "", 619 "",
414 "clientstack", 620 "clientstack",
415 m_scene.Name, 621 Scene.Name,
416 StatType.Pull, 622 StatType.Pull,
417 stat => stat.Value = m_incomingPacketPool.Count, 623 stat => stat.Value = m_incomingPacketPool.Count,
418 StatVerbosity.Debug); 624 StatVerbosity.Debug);
@@ -423,7 +629,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
423 /// <summary> 629 /// <summary>
424 /// Disables pool stats. 630 /// Disables pool stats.
425 /// </summary> 631 /// </summary>
426 private void DisablePoolStats() 632 protected internal void DisablePoolStats()
427 { 633 {
428 StatsManager.DeregisterStat(m_poolCountStat); 634 StatsManager.DeregisterStat(m_poolCountStat);
429 m_poolCountStat = null; 635 m_poolCountStat = null;
@@ -456,7 +662,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
456 662
457 public void AddScene(IScene scene) 663 public void AddScene(IScene scene)
458 { 664 {
459 if (m_scene != null) 665 if (Scene != null)
460 { 666 {
461 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene"); 667 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene");
462 return; 668 return;
@@ -468,8 +674,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
468 return; 674 return;
469 } 675 }
470 676
471 m_scene = (Scene)scene; 677 Scene = (Scene)scene;
472 m_location = new Location(m_scene.RegionInfo.RegionHandle); 678 m_location = new Location(Scene.RegionInfo.RegionHandle);
679
680 IpahEngine
681 = new JobEngine(
682 string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name),
683 "INCOMING PACKET ASYNC HANDLING ENGINE");
684
685 OqrEngine
686 = new JobEngine(
687 string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name),
688 "OUTGOING QUEUE REFILL ENGINE");
689
690 StatsManager.RegisterStat(
691 new Stat(
692 "InboxPacketsCount",
693 "Number of LL protocol packets waiting for the second stage of processing after initial receive.",
694 "Number of LL protocol packets waiting for the second stage of processing after initial receive.",
695 "",
696 "clientstack",
697 scene.Name,
698 StatType.Pull,
699 MeasuresOfInterest.AverageChangeOverTime,
700 stat => stat.Value = packetInbox.Count,
701 StatVerbosity.Debug));
473 702
474 // XXX: These stats are also pool stats but we register them separately since they are currently not 703 // XXX: These stats are also pool stats but we register them separately since they are currently not
475 // turned on and off by EnablePools()/DisablePools() 704 // turned on and off by EnablePools()/DisablePools()
@@ -479,7 +708,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
479 "Packets reused", 708 "Packets reused",
480 "Number of packets reused out of all requests to the packet pool", 709 "Number of packets reused out of all requests to the packet pool",
481 "clientstack", 710 "clientstack",
482 m_scene.Name, 711 Scene.Name,
483 StatType.Pull, 712 StatType.Pull,
484 stat => 713 stat =>
485 { PercentageStat pstat = (PercentageStat)stat; 714 { PercentageStat pstat = (PercentageStat)stat;
@@ -493,7 +722,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
493 "Packet data blocks reused", 722 "Packet data blocks reused",
494 "Number of data blocks reused out of all requests to the packet pool", 723 "Number of data blocks reused out of all requests to the packet pool",
495 "clientstack", 724 "clientstack",
496 m_scene.Name, 725 Scene.Name,
497 StatType.Pull, 726 StatType.Pull,
498 stat => 727 stat =>
499 { PercentageStat pstat = (PercentageStat)stat; 728 { PercentageStat pstat = (PercentageStat)stat;
@@ -508,7 +737,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
508 "The number of objects currently stored within the packet pool", 737 "The number of objects currently stored within the packet pool",
509 "", 738 "",
510 "clientstack", 739 "clientstack",
511 m_scene.Name, 740 Scene.Name,
512 StatType.Pull, 741 StatType.Pull,
513 stat => stat.Value = PacketPool.Instance.PacketsPooled, 742 stat => stat.Value = PacketPool.Instance.PacketsPooled,
514 StatVerbosity.Debug)); 743 StatVerbosity.Debug));
@@ -520,132 +749,57 @@ namespace OpenSim.Region.ClientStack.LindenUDP
520 "The number of objects currently stored within the packet data block pool", 749 "The number of objects currently stored within the packet data block pool",
521 "", 750 "",
522 "clientstack", 751 "clientstack",
523 m_scene.Name, 752 Scene.Name,
524 StatType.Pull, 753 StatType.Pull,
525 stat => stat.Value = PacketPool.Instance.BlocksPooled, 754 stat => stat.Value = PacketPool.Instance.BlocksPooled,
526 StatVerbosity.Debug)); 755 StatVerbosity.Debug));
756
757 StatsManager.RegisterStat(
758 new Stat(
759 "OutgoingPacketsQueuedCount",
760 "Packets queued for outgoing send",
761 "Number of queued outgoing packets across all connections",
762 "",
763 "clientstack",
764 Scene.Name,
765 StatType.Pull,
766 MeasuresOfInterest.AverageChangeOverTime,
767 stat => stat.Value = GetTotalQueuedOutgoingPackets(),
768 StatVerbosity.Info));
769
770 StatsManager.RegisterStat(
771 new Stat(
772 "IncomingPacketAsyncRequestsWaiting",
773 "Number of incoming packets waiting for async processing in engine.",
774 "",
775 "",
776 "clientstack",
777 Scene.Name,
778 StatType.Pull,
779 MeasuresOfInterest.None,
780 stat => stat.Value = IpahEngine.JobsWaiting,
781 StatVerbosity.Debug));
782
783 StatsManager.RegisterStat(
784 new Stat(
785 "OQRERequestsWaiting",
786 "Number of outgong queue refill requests waiting for processing.",
787 "",
788 "",
789 "clientstack",
790 Scene.Name,
791 StatType.Pull,
792 MeasuresOfInterest.None,
793 stat => stat.Value = OqrEngine.JobsWaiting,
794 StatVerbosity.Debug));
527 795
528 // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by 796 // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by
529 // scene name 797 // scene name
530 if (UsePools) 798 if (UsePools)
531 EnablePoolStats(); 799 EnablePoolStats();
532 800
533 MainConsole.Instance.Commands.AddCommand( 801 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this);
534 "Debug", 802 commands.Register();
535 false,
536 "debug lludp start",
537 "debug lludp start <in|out|all>",
538 "Control LLUDP packet processing.",
539 "No effect if packet processing has already started.\n"
540 + "in - start inbound processing.\n"
541 + "out - start outbound processing.\n"
542 + "all - start in and outbound processing.\n",
543 HandleStartCommand);
544
545 MainConsole.Instance.Commands.AddCommand(
546 "Debug",
547 false,
548 "debug lludp stop",
549 "debug lludp stop <in|out|all>",
550 "Stop LLUDP packet processing.",
551 "No effect if packet processing has already stopped.\n"
552 + "in - stop inbound processing.\n"
553 + "out - stop outbound processing.\n"
554 + "all - stop in and outbound processing.\n",
555 HandleStopCommand);
556
557 MainConsole.Instance.Commands.AddCommand(
558 "Debug",
559 false,
560 "debug lludp pool",
561 "debug lludp pool <on|off>",
562 "Turn object pooling within the lludp component on or off.",
563 HandlePoolCommand);
564
565 MainConsole.Instance.Commands.AddCommand(
566 "Debug",
567 false,
568 "debug lludp status",
569 "debug lludp status",
570 "Return status of LLUDP packet processing.",
571 HandleStatusCommand);
572 }
573
574 private void HandleStartCommand(string module, string[] args)
575 {
576 if (args.Length != 4)
577 {
578 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
579 return;
580 }
581
582 string subCommand = args[3];
583
584 if (subCommand == "in" || subCommand == "all")
585 StartInbound();
586
587 if (subCommand == "out" || subCommand == "all")
588 StartOutbound();
589 }
590
591 private void HandleStopCommand(string module, string[] args)
592 {
593 if (args.Length != 4)
594 {
595 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>");
596 return;
597 }
598
599 string subCommand = args[3];
600
601 if (subCommand == "in" || subCommand == "all")
602 StopInbound();
603
604 if (subCommand == "out" || subCommand == "all")
605 StopOutbound();
606 }
607
608 private void HandlePoolCommand(string module, string[] args)
609 {
610 if (args.Length != 4)
611 {
612 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
613 return;
614 }
615
616 string enabled = args[3];
617
618 if (enabled == "on")
619 {
620 if (EnablePools())
621 {
622 EnablePoolStats();
623 MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name);
624 }
625 }
626 else if (enabled == "off")
627 {
628 if (DisablePools())
629 {
630 DisablePoolStats();
631 MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name);
632 }
633 }
634 else
635 {
636 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
637 }
638 }
639
640 private void HandleStatusCommand(string module, string[] args)
641 {
642 MainConsole.Instance.OutputFormat(
643 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
644
645 MainConsole.Instance.OutputFormat(
646 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
647
648 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off");
649 } 803 }
650 804
651 public bool HandlesRegion(Location x) 805 public bool HandlesRegion(Location x)
@@ -653,45 +807,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP
653 return x == m_location; 807 return x == m_location;
654 } 808 }
655 809
656 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) 810 public int GetTotalQueuedOutgoingPackets()
657 { 811 {
658 // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way 812 int total = 0;
659 if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
660 allowSplitting = false;
661 813
662 if (allowSplitting && packet.HasVariableBlocks) 814 foreach (ScenePresence sp in Scene.GetScenePresences())
663 { 815 {
664 byte[][] datas = packet.ToBytesMultiple(); 816 // XXX: Need a better way to determine which IClientAPIs have UDPClients (NPCs do not, for instance).
665 int packetCount = datas.Length; 817 if (sp.ControllingClient is LLClientView)
666
667 if (packetCount < 1)
668 m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);
669
670 for (int i = 0; i < packetCount; i++)
671 { 818 {
672 byte[] data = datas[i]; 819 LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
673 m_scene.ForEachClient( 820 total += udpClient.GetTotalPacketsQueuedCount();
674 delegate(IClientAPI client)
675 {
676 if (client is LLClientView)
677 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
678 }
679 );
680 } 821 }
681 } 822 }
682 else 823
683 { 824 return total;
684 byte[] data = packet.ToBytes();
685 m_scene.ForEachClient(
686 delegate(IClientAPI client)
687 {
688 if (client is LLClientView)
689 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
690 }
691 );
692 }
693 } 825 }
694 826
827// public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
828// {
829// // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
830// if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
831// allowSplitting = false;
832//
833// if (allowSplitting && packet.HasVariableBlocks)
834// {
835// byte[][] datas = packet.ToBytesMultiple();
836// int packetCount = datas.Length;
837//
838// if (packetCount < 1)
839// m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);
840//
841// for (int i = 0; i < packetCount; i++)
842// {
843// byte[] data = datas[i];
844// m_scene.ForEachClient(
845// delegate(IClientAPI client)
846// {
847// if (client is LLClientView)
848// SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
849// }
850// );
851// }
852// }
853// else
854// {
855// byte[] data = packet.ToBytes();
856// m_scene.ForEachClient(
857// delegate(IClientAPI client)
858// {
859// if (client is LLClientView)
860// SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
861// }
862// );
863// }
864// }
865
695 /// <summary> 866 /// <summary>
696 /// Start the process of sending a packet to the client. 867 /// Start the process of sending a packet to the client.
697 /// </summary> 868 /// </summary>
@@ -710,6 +881,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
710 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) 881 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
711 allowSplitting = false; 882 allowSplitting = false;
712 883
884 bool packetQueued = false;
885
713 if (allowSplitting && packet.HasVariableBlocks) 886 if (allowSplitting && packet.HasVariableBlocks)
714 { 887 {
715 byte[][] datas = packet.ToBytesMultiple(); 888 byte[][] datas = packet.ToBytesMultiple();
@@ -721,16 +894,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
721 for (int i = 0; i < packetCount; i++) 894 for (int i = 0; i < packetCount; i++)
722 { 895 {
723 byte[] data = datas[i]; 896 byte[] data = datas[i];
724 SendPacketData(udpClient, data, packet.Type, category, method); 897 if (!SendPacketData(udpClient, data, packet.Type, category, method))
898 packetQueued = true;
725 } 899 }
726 } 900 }
727 else 901 else
728 { 902 {
729 byte[] data = packet.ToBytes(); 903 byte[] data = packet.ToBytes();
730 SendPacketData(udpClient, data, packet.Type, category, method); 904 if (!SendPacketData(udpClient, data, packet.Type, category, method))
905 packetQueued = true;
731 } 906 }
732 907
733 PacketPool.Instance.ReturnPacket(packet); 908 PacketPool.Instance.ReturnPacket(packet);
909
910 if (packetQueued)
911 m_dataPresentEvent.Set();
734 } 912 }
735 913
736 /// <summary> 914 /// <summary>
@@ -744,7 +922,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
744 /// The method to call if the packet is not acked by the client. If null, then a standard 922 /// The method to call if the packet is not acked by the client. If null, then a standard
745 /// resend of the packet is done. 923 /// resend of the packet is done.
746 /// </param> 924 /// </param>
747 public void SendPacketData( 925 /// <returns>true if the data was sent immediately, false if it was queued for sending</returns>
926 public bool SendPacketData(
748 LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method) 927 LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
749 { 928 {
750 int dataLength = data.Length; 929 int dataLength = data.Length;
@@ -801,15 +980,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
801 #region Queue or Send 980 #region Queue or Send
802 981
803 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); 982 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
983
804 // If we were not provided a method for handling unacked, use the UDPServer default method 984 // If we were not provided a method for handling unacked, use the UDPServer default method
805 outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); 985 if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0)
986 outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
806 987
807 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will 988 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
808 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object 989 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object
809 // packet so that it isn't sent before a queued update packet. 990 // packet so that it isn't sent before a queued update packet.
810 bool requestQueue = type == PacketType.KillObject; 991 bool forceQueue = (type == PacketType.KillObject);
811 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) 992
993// if (type == PacketType.ImprovedTerseObjectUpdate)
994// {
995// m_log.DebugFormat("Direct send ITOU to {0} in {1}", udpClient.AgentID, Scene.Name);
996// SendPacketFinal(outgoingPacket);
997// return false;
998// }
999// else
1000// {
1001 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forceQueue))
1002 {
812 SendPacketFinal(outgoingPacket); 1003 SendPacketFinal(outgoingPacket);
1004 return true;
1005 }
1006 else
1007 {
1008 return false;
1009 }
1010// }
813 1011
814 #endregion Queue or Send 1012 #endregion Queue or Send
815 } 1013 }
@@ -885,7 +1083,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
885 // Fire this out on a different thread so that we don't hold up outgoing packet processing for 1083 // Fire this out on a different thread so that we don't hold up outgoing packet processing for
886 // everybody else if this is being called due to an ack timeout. 1084 // everybody else if this is being called due to an ack timeout.
887 // This is the same as processing as the async process of a logout request. 1085 // This is the same as processing as the async process of a logout request.
888 Util.FireAndForget(o => DeactivateClientDueToTimeout(client)); 1086 Util.FireAndForget(
1087 o => DeactivateClientDueToTimeout(client, timeoutTicks), null, "LLUDPServer.DeactivateClientDueToTimeout");
889 1088
890 return; 1089 return;
891 } 1090 }
@@ -981,7 +1180,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
981 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); 1180 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
982 outgoingPacket.SequenceNumber = sequenceNumber; 1181 outgoingPacket.SequenceNumber = sequenceNumber;
983 1182
984 if (isReliable) 1183 if (udpClient.ProcessUnackedSends && isReliable)
985 { 1184 {
986 // Add this packet to the list of ACK responses we are waiting on from the server 1185 // Add this packet to the list of ACK responses we are waiting on from the server
987 udpClient.NeedAcks.Add(outgoingPacket); 1186 udpClient.NeedAcks.Add(outgoingPacket);
@@ -990,6 +1189,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
990 else 1189 else
991 { 1190 {
992 Interlocked.Increment(ref udpClient.PacketsResent); 1191 Interlocked.Increment(ref udpClient.PacketsResent);
1192
1193 // We're not going to worry about interlock yet since its not currently critical that this total count
1194 // is 100% correct
1195 PacketsResentCount++;
993 } 1196 }
994 1197
995 #endregion Sequence Number Assignment 1198 #endregion Sequence Number Assignment
@@ -997,6 +1200,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
997 // Stats tracking 1200 // Stats tracking
998 Interlocked.Increment(ref udpClient.PacketsSent); 1201 Interlocked.Increment(ref udpClient.PacketsSent);
999 1202
1203 // We're not going to worry about interlock yet since its not currently critical that this total count
1204 // is 100% correct
1205 PacketsSentCount++;
1206
1207 if (udpClient.DebugDataOutLevel > 0)
1208 m_log.DebugFormat(
1209 "[LLUDPSERVER]: Sending packet #{0} (rel: {1}, res: {2}) to {3} from {4}",
1210 outgoingPacket.SequenceNumber, isReliable, isResend, udpClient.AgentID, Scene.Name);
1211
1000 // Put the UDP payload on the wire 1212 // Put the UDP payload on the wire
1001 AsyncBeginSend(buffer); 1213 AsyncBeginSend(buffer);
1002 1214
@@ -1004,6 +1216,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1004 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; 1216 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
1005 } 1217 }
1006 1218
1219 private void RecordMalformedInboundPacket(IPEndPoint endPoint)
1220 {
1221// if (m_malformedCount < 100)
1222// m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
1223
1224 IncomingMalformedPacketCount++;
1225
1226 if ((IncomingMalformedPacketCount % 10000) == 0)
1227 m_log.WarnFormat(
1228 "[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack. Last was from {1}",
1229 IncomingMalformedPacketCount, endPoint);
1230 }
1231
1007 public override void PacketReceived(UDPPacketBuffer buffer) 1232 public override void PacketReceived(UDPPacketBuffer buffer)
1008 { 1233 {
1009 // Debugging/Profiling 1234 // Debugging/Profiling
@@ -1025,6 +1250,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1025// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", 1250// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
1026// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1251// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1027 1252
1253 RecordMalformedInboundPacket(endPoint);
1254
1028 return; // Drop undersized packet 1255 return; // Drop undersized packet
1029 } 1256 }
1030 1257
@@ -1043,6 +1270,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1043// "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}", 1270// "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}",
1044// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1271// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1045 1272
1273 RecordMalformedInboundPacket(endPoint);
1274
1046 return; // Malformed header 1275 return; // Malformed header
1047 } 1276 }
1048 1277
@@ -1058,34 +1287,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1058 // Only allocate a buffer for zerodecoding if the packet is zerocoded 1287 // Only allocate a buffer for zerodecoding if the packet is zerocoded
1059 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1288 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
1060 } 1289 }
1061 catch (MalformedDataException)
1062 {
1063 }
1064 catch (IndexOutOfRangeException)
1065 {
1066// m_log.WarnFormat(
1067// "[LLUDPSERVER]: Dropping short packet received from {0} in {1}",
1068// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1069
1070 return; // Drop short packet
1071 }
1072 catch (Exception e) 1290 catch (Exception e)
1073 { 1291 {
1074 if (m_malformedCount < 100) 1292 if (IncomingMalformedPacketCount < 100)
1075 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 1293 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
1076
1077 m_malformedCount++;
1078
1079 if ((m_malformedCount % 100000) == 0)
1080 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
1081 } 1294 }
1082 1295
1083 // Fail-safe check 1296 // Fail-safe check
1084 if (packet == null) 1297 if (packet == null)
1085 { 1298 {
1086 m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}:", 1299 if (IncomingMalformedPacketCount < 100)
1087 buffer.DataLength, buffer.RemoteEndPoint); 1300 {
1088 m_log.Error(Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); 1301 m_log.WarnFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}, data {2}:",
1302 buffer.DataLength, buffer.RemoteEndPoint, Utils.BytesToHexString(buffer.Data, buffer.DataLength, null));
1303 }
1304
1305 RecordMalformedInboundPacket(endPoint);
1306
1089 return; 1307 return;
1090 } 1308 }
1091 1309
@@ -1100,16 +1318,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1100 // buffer. 1318 // buffer.
1101 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1319 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1102 1320
1103 Util.FireAndForget(HandleUseCircuitCode, array); 1321 Util.FireAndForget(HandleUseCircuitCode, array, "LLUDPServer.HandleUseCircuitCode");
1322
1323 return;
1324 }
1325 else if (packet.Type == PacketType.CompleteAgentMovement)
1326 {
1327 // Send ack straight away to let the viewer know that we got it.
1328 SendAckImmediate(endPoint, packet.Header.Sequence);
1329
1330 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1331 // buffer.
1332 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1333
1334 Util.FireAndForget(
1335 HandleCompleteMovementIntoRegion, array, "LLUDPServer.HandleCompleteMovementIntoRegion");
1104 1336
1105 return; 1337 return;
1106 } 1338 }
1107 1339
1108 // Determine which agent this packet came from 1340 // Determine which agent this packet came from
1109 IClientAPI client; 1341 IClientAPI client;
1110 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) 1342 if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1111 { 1343 {
1112 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1344 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
1345
1346 IncomingOrphanedPacketCount++;
1347
1348 if ((IncomingOrphanedPacketCount % 10000) == 0)
1349 m_log.WarnFormat(
1350 "[LLUDPSERVER]: Received {0} orphaned packets so far. Last was from {1}",
1351 IncomingOrphanedPacketCount, endPoint);
1352
1113 return; 1353 return;
1114 } 1354 }
1115 1355
@@ -1128,30 +1368,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1128 1368
1129 #region ACK Receiving 1369 #region ACK Receiving
1130 1370
1131 // Handle appended ACKs 1371 if (udpClient.ProcessUnackedSends)
1132 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
1133 { 1372 {
1134// m_log.DebugFormat( 1373 // Handle appended ACKs
1135// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", 1374 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
1136// packet.Header.AckList.Length, client.Name, m_scene.Name); 1375 {
1376 // m_log.DebugFormat(
1377 // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1378 // packet.Header.AckList.Length, client.Name, m_scene.Name);
1137 1379
1138 for (int i = 0; i < packet.Header.AckList.Length; i++) 1380 for (int i = 0; i < packet.Header.AckList.Length; i++)
1139 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 1381 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
1140 } 1382 }
1141 1383
1142 // Handle PacketAck packets 1384 // Handle PacketAck packets
1143 if (packet.Type == PacketType.PacketAck) 1385 if (packet.Type == PacketType.PacketAck)
1144 { 1386 {
1145 PacketAckPacket ackPacket = (PacketAckPacket)packet; 1387 PacketAckPacket ackPacket = (PacketAckPacket)packet;
1146 1388
1147// m_log.DebugFormat( 1389 // m_log.DebugFormat(
1148// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", 1390 // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
1149// ackPacket.Packets.Length, client.Name, m_scene.Name); 1391 // ackPacket.Packets.Length, client.Name, m_scene.Name);
1150 1392
1151 for (int i = 0; i < ackPacket.Packets.Length; i++) 1393 for (int i = 0; i < ackPacket.Packets.Length; i++)
1152 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); 1394 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
1153 1395
1154 // We don't need to do anything else with PacketAck packets 1396 // We don't need to do anything else with PacketAck packets
1397 return;
1398 }
1399 }
1400 else if (packet.Type == PacketType.PacketAck)
1401 {
1155 return; 1402 return;
1156 } 1403 }
1157 1404
@@ -1185,6 +1432,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1185 1432
1186 #region Incoming Packet Accounting 1433 #region Incoming Packet Accounting
1187 1434
1435 // We're not going to worry about interlock yet since its not currently critical that this total count
1436 // is 100% correct
1437 if (packet.Header.Resent)
1438 IncomingPacketsResentCount++;
1439
1188 // Check the archive of received reliable packet IDs to see whether we already received this packet 1440 // Check the archive of received reliable packet IDs to see whether we already received this packet
1189 if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence)) 1441 if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence))
1190 { 1442 {
@@ -1207,6 +1459,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1207 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1459 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1208 #endregion BinaryStats 1460 #endregion BinaryStats
1209 1461
1462 if (packet.Type == PacketType.AgentUpdate)
1463 {
1464 if (DiscardInboundAgentUpdates)
1465 return;
1466
1467 ((LLClientView)client).TotalAgentUpdates++;
1468
1469 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
1470
1471 LLClientView llClient = client as LLClientView;
1472 if (agentUpdate.AgentData.SessionID != client.SessionId
1473 || agentUpdate.AgentData.AgentID != client.AgentId
1474 || !(llClient == null || llClient.CheckAgentUpdateSignificance(agentUpdate.AgentData)) )
1475 {
1476 PacketPool.Instance.ReturnPacket(packet);
1477 return;
1478 }
1479 }
1480
1210 #region Ping Check Handling 1481 #region Ping Check Handling
1211 1482
1212 if (packet.Type == PacketType.StartPingCheck) 1483 if (packet.Type == PacketType.StartPingCheck)
@@ -1266,8 +1537,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1266 static object binStatsLogLock = new object(); 1537 static object binStatsLogLock = new object();
1267 static string binStatsDir = ""; 1538 static string binStatsDir = "";
1268 1539
1540 //for Aggregated In/Out BW logging
1541 static bool m_aggregatedBWStats = false;
1542 static long m_aggregatedBytesIn = 0;
1543 static long m_aggregatedByestOut = 0;
1544 static object aggBWStatsLock = new object();
1545
1546 public static long AggregatedLLUDPBytesIn
1547 {
1548 get { return m_aggregatedBytesIn; }
1549 }
1550 public static long AggregatedLLUDPBytesOut
1551 {
1552 get {return m_aggregatedByestOut;}
1553 }
1554
1269 public static void LogPacketHeader(bool incoming, uint circuit, byte flags, PacketType packetType, ushort size) 1555 public static void LogPacketHeader(bool incoming, uint circuit, byte flags, PacketType packetType, ushort size)
1270 { 1556 {
1557 if (m_aggregatedBWStats)
1558 {
1559 lock (aggBWStatsLock)
1560 {
1561 if (incoming)
1562 m_aggregatedBytesIn += size;
1563 else
1564 m_aggregatedByestOut += size;
1565 }
1566 }
1567
1271 if (!m_shouldCollectStats) return; 1568 if (!m_shouldCollectStats) return;
1272 1569
1273 // Binary logging format is TTTTTTTTCCCCFPPPSS, T=Time, C=Circuit, F=Flags, P=PacketType, S=size 1570 // Binary logging format is TTTTTTTTCCCCFPPPSS, T=Time, C=Circuit, F=Flags, P=PacketType, S=size
@@ -1344,7 +1641,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1344 1641
1345 m_log.DebugFormat( 1642 m_log.DebugFormat(
1346 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", 1643 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
1347 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); 1644 uccp.CircuitCode.Code, Scene.RegionInfo.RegionName, endPoint);
1348 1645
1349 AuthenticateResponse sessionInfo; 1646 AuthenticateResponse sessionInfo;
1350 if (IsClientAuthorized(uccp, out sessionInfo)) 1647 if (IsClientAuthorized(uccp, out sessionInfo))
@@ -1365,14 +1662,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1365 1662
1366 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1663 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1367 if (client != null) 1664 if (client != null)
1368 client.SceneAgent.SendInitialDataToMe(); 1665 {
1666 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1667 bool tp = (aCircuit.teleportFlags > 0);
1668 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from
1669 if (!tp && !client.SceneAgent.SentInitialDataToClient)
1670 client.SceneAgent.SendInitialDataToClient();
1671 }
1369 } 1672 }
1370 else 1673 else
1371 { 1674 {
1372 // Don't create clients for unauthorized requesters. 1675 // Don't create clients for unauthorized requesters.
1373 m_log.WarnFormat( 1676 m_log.WarnFormat(
1374 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1677 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1375 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1678 uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1376 } 1679 }
1377 1680
1378 // m_log.DebugFormat( 1681 // m_log.DebugFormat(
@@ -1392,6 +1695,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1392 } 1695 }
1393 } 1696 }
1394 1697
1698 private void HandleCompleteMovementIntoRegion(object o)
1699 {
1700 IPEndPoint endPoint = null;
1701 IClientAPI client = null;
1702
1703 try
1704 {
1705 object[] array = (object[])o;
1706 endPoint = (IPEndPoint)array[0];
1707 CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1];
1708
1709 m_log.DebugFormat(
1710 "[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, Scene.Name);
1711
1712 // Determine which agent this packet came from
1713 // We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination
1714 // simulator with no existing child presence, the viewer (at least LL 3.3.4) will send UseCircuitCode
1715 // and then CompleteAgentMovement immediately without waiting for an ack. As we are now handling these
1716 // packets asynchronously, we need to account for this thread proceeding more quickly than the
1717 // UseCircuitCode thread.
1718 int count = 40;
1719 while (count-- > 0)
1720 {
1721 if (Scene.TryGetClient(endPoint, out client))
1722 {
1723 if (!client.IsActive)
1724 {
1725 // This check exists to catch a condition where the client has been closed by another thread
1726 // but has not yet been removed from the client manager (and possibly a new connection has
1727 // not yet been established).
1728 m_log.DebugFormat(
1729 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.",
1730 endPoint, client.Name, Scene.Name);
1731 }
1732 else if (client.SceneAgent == null)
1733 {
1734 // This check exists to catch a condition where the new client has been added to the client
1735 // manager but the SceneAgent has not yet been set in Scene.AddNewAgent(). If we are too
1736 // eager, then the new ScenePresence may not have registered a listener for this messsage
1737 // before we try to process it.
1738 // XXX: A better long term fix may be to add the SceneAgent before the client is added to
1739 // the client manager
1740 m_log.DebugFormat(
1741 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.",
1742 endPoint, client.Name, Scene.Name);
1743 }
1744 else
1745 {
1746 break;
1747 }
1748 }
1749 else
1750 {
1751 m_log.DebugFormat(
1752 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.",
1753 endPoint, Scene.Name);
1754 }
1755
1756 Thread.Sleep(200);
1757 }
1758
1759 if (client == null)
1760 {
1761 m_log.DebugFormat(
1762 "[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.",
1763 endPoint, Scene.Name);
1764
1765 return;
1766 }
1767 else if (!client.IsActive || client.SceneAgent == null)
1768 {
1769 // This check exists to catch a condition where the client has been closed by another thread
1770 // but has not yet been removed from the client manager.
1771 // The packet could be simply ignored but it is useful to know if this condition occurred for other debugging
1772 // purposes.
1773 m_log.DebugFormat(
1774 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.",
1775 endPoint, client.Name, Scene.Name);
1776
1777 return;
1778 }
1779
1780 IncomingPacket incomingPacket1;
1781
1782 // Inbox insertion
1783 if (UsePools)
1784 {
1785 incomingPacket1 = m_incomingPacketPool.GetObject();
1786 incomingPacket1.Client = (LLClientView)client;
1787 incomingPacket1.Packet = packet;
1788 }
1789 else
1790 {
1791 incomingPacket1 = new IncomingPacket((LLClientView)client, packet);
1792 }
1793
1794 packetInbox.Enqueue(incomingPacket1);
1795 }
1796 catch (Exception e)
1797 {
1798 m_log.ErrorFormat(
1799 "[LLUDPSERVER]: CompleteAgentMovement handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1800 endPoint != null ? endPoint.ToString() : "n/a",
1801 client != null ? client.Name : "unknown",
1802 client != null ? client.AgentId.ToString() : "unknown",
1803 e.Message,
1804 e.StackTrace);
1805 }
1806 }
1807
1395 /// <summary> 1808 /// <summary>
1396 /// Send an ack immediately to the given endpoint. 1809 /// Send an ack immediately to the given endpoint.
1397 /// </summary> 1810 /// </summary>
@@ -1454,12 +1867,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1454 // consistently, this lock could probably be removed. 1867 // consistently, this lock could probably be removed.
1455 lock (this) 1868 lock (this)
1456 { 1869 {
1457 if (!m_scene.TryGetClient(agentID, out client)) 1870 if (!Scene.TryGetClient(agentID, out client))
1458 { 1871 {
1459 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1872 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1460 1873
1461 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1874 client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1462 client.OnLogout += LogoutHandler; 1875 client.OnLogout += LogoutHandler;
1876 client.DebugPacketLevel = DefaultClientPacketDebugLevel;
1463 1877
1464 ((LLClientView)client).DisableFacelights = m_disableFacelights; 1878 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1465 1879
@@ -1478,25 +1892,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1478 /// regular client pings. 1892 /// regular client pings.
1479 /// </remarks> 1893 /// </remarks>
1480 /// <param name='client'></param> 1894 /// <param name='client'></param>
1481 private void DeactivateClientDueToTimeout(LLClientView client) 1895 /// <param name='timeoutTicks'></param>
1896 private void DeactivateClientDueToTimeout(LLClientView client, int timeoutTicks)
1482 { 1897 {
1483 lock (client.CloseSyncLock) 1898 lock (client.CloseSyncLock)
1484 { 1899 {
1900 ClientLogoutsDueToNoReceives++;
1901
1485 m_log.WarnFormat( 1902 m_log.WarnFormat(
1486 "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", 1903 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
1487 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); 1904 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name);
1488
1489 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
1490 1905
1491 if (!client.SceneAgent.IsChildAgent) 1906 if (!client.SceneAgent.IsChildAgent)
1492 client.Kick("Simulator logged you out due to connection timeout"); 1907 client.Kick("Simulator logged you out due to connection timeout.");
1493
1494 client.CloseWithoutChecks();
1495 } 1908 }
1909
1910 Scene.CloseAgent(client.AgentId, true);
1496 } 1911 }
1497 1912
1498 private void IncomingPacketHandler() 1913 private void IncomingPacketHandler()
1499 { 1914 {
1915 Thread.CurrentThread.Priority = ThreadPriority.Highest;
1916
1500 // Set this culture for the thread that incoming packets are received 1917 // Set this culture for the thread that incoming packets are received
1501 // on to en-US to avoid number parsing issues 1918 // on to en-US to avoid number parsing issues
1502 Culture.SetCurrentCulture(); 1919 Culture.SetCurrentCulture();
@@ -1507,6 +1924,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1507 { 1924 {
1508 IncomingPacket incomingPacket = null; 1925 IncomingPacket incomingPacket = null;
1509 1926
1927 /*
1510 // HACK: This is a test to try and rate limit packet handling on Mono. 1928 // HACK: This is a test to try and rate limit packet handling on Mono.
1511 // If it works, a more elegant solution can be devised 1929 // If it works, a more elegant solution can be devised
1512 if (Util.FireAndForgetCount() < 2) 1930 if (Util.FireAndForgetCount() < 2)
@@ -1514,6 +1932,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1514 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping"); 1932 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping");
1515 Thread.Sleep(30); 1933 Thread.Sleep(30);
1516 } 1934 }
1935 */
1517 1936
1518 if (packetInbox.Dequeue(100, ref incomingPacket)) 1937 if (packetInbox.Dequeue(100, ref incomingPacket))
1519 { 1938 {
@@ -1540,6 +1959,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1540 1959
1541 private void OutgoingPacketHandler() 1960 private void OutgoingPacketHandler()
1542 { 1961 {
1962 Thread.CurrentThread.Priority = ThreadPriority.Highest;
1963
1543 // Set this culture for the thread that outgoing packets are sent 1964 // Set this culture for the thread that outgoing packets are sent
1544 // on to en-US to avoid number parsing issues 1965 // on to en-US to avoid number parsing issues
1545 Culture.SetCurrentCulture(); 1966 Culture.SetCurrentCulture();
@@ -1602,14 +2023,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1602 2023
1603 // Handle outgoing packets, resends, acknowledgements, and pings for each 2024 // Handle outgoing packets, resends, acknowledgements, and pings for each
1604 // client. m_packetSent will be set to true if a packet is sent 2025 // client. m_packetSent will be set to true if a packet is sent
1605 m_scene.ForEachClient(clientPacketHandler); 2026 Scene.ForEachClient(clientPacketHandler);
1606 2027
1607 m_currentOutgoingClient = null; 2028 m_currentOutgoingClient = null;
1608 2029
1609 // If nothing was sent, sleep for the minimum amount of time before a 2030 // If nothing was sent, sleep for the minimum amount of time before a
1610 // token bucket could get more tokens 2031 // token bucket could get more tokens
2032 //if (!m_packetSent)
2033 // Thread.Sleep((int)TickCountResolution);
2034 //
2035 // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with
2036 // modern mono it reduces CPU base load since there is no more continuous polling.
1611 if (!m_packetSent) 2037 if (!m_packetSent)
1612 Thread.Sleep((int)TickCountResolution); 2038 m_dataPresentEvent.WaitOne(100);
1613 2039
1614 Watchdog.UpdateThread(); 2040 Watchdog.UpdateThread();
1615 } 2041 }
@@ -1635,7 +2061,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1635 2061
1636 if (udpClient.IsConnected) 2062 if (udpClient.IsConnected)
1637 { 2063 {
1638 if (m_resendUnacked) 2064 if (udpClient.ProcessUnackedSends && m_resendUnacked)
1639 HandleUnacked(llClient); 2065 HandleUnacked(llClient);
1640 2066
1641 if (m_sendAcks) 2067 if (m_sendAcks)
@@ -1764,7 +2190,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1764 watch1.Reset(); 2190 watch1.Reset();
1765 2191
1766 // reuse this -- it's every ~100ms 2192 // reuse this -- it's every ~100ms
1767 if (m_scene.EmergencyMonitoring && nticks % 100 == 0) 2193 if (Scene.EmergencyMonitoring && nticks % 100 == 0)
1768 { 2194 {
1769 m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})", 2195 m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})",
1770 avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent); 2196 avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent);
@@ -1813,7 +2239,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1813 { 2239 {
1814 m_log.DebugFormat( 2240 m_log.DebugFormat(
1815 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 2241 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1816 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 2242 packet.Type, client.Name, Scene.RegionInfo.RegionName);
1817 } 2243 }
1818 2244
1819 IncomingPacketsProcessed++; 2245 IncomingPacketsProcessed++;
@@ -1826,8 +2252,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1826 if (!client.IsLoggingOut) 2252 if (!client.IsLoggingOut)
1827 { 2253 {
1828 client.IsLoggingOut = true; 2254 client.IsLoggingOut = true;
1829 client.Close(); 2255 Scene.CloseAgent(client.AgentId, false);
1830 } 2256 }
1831 } 2257 }
1832 } 2258 }
1833} \ No newline at end of file 2259}