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.cs778
1 files changed, 381 insertions, 397 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 4528714..b575ed9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -51,60 +51,59 @@ namespace OpenSim.Region.ClientStack.LindenUDP
51 /// A shim around LLUDPServer that implements the IClientNetworkServer interface 51 /// A shim around LLUDPServer that implements the IClientNetworkServer interface
52 /// </summary> 52 /// </summary>
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LLUDPServerShim")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LLUDPServerShim")]
54 public sealed class LLUDPServerShim : INonSharedRegionModule 54 public class LLUDPServerShim : INonSharedRegionModule
55 { 55 {
56 private bool m_Enabled = true; 56 protected IConfigSource m_Config;
57 private IConfigSource m_Config; 57 protected LLUDPServer m_udpServer;
58 LLUDPServer m_udpServer;
59 58
60 #region INonSharedRegionModule 59 #region INonSharedRegionModule
61 public string Name 60 public virtual string Name
62 { 61 {
63 get { return "LLUDPServerShim"; } 62 get { return "LLUDPServerShim"; }
64 } 63 }
65 64
66 public Type ReplaceableInterface 65 public virtual Type ReplaceableInterface
67 { 66 {
68 get { return null; } 67 get { return null; }
69 } 68 }
70 69
71 public void Initialise(IConfigSource source) 70 public virtual void Initialise(IConfigSource source)
72 { 71 {
73 m_Config = source; 72 m_Config = source;
74 } 73 }
75 74
76 public void Close() 75 public virtual void Close()
77 { 76 {
78 } 77 }
79 78
80 public void AddRegion(Scene scene) 79 public virtual void AddRegion(Scene scene)
81 { 80 {
82 uint port = (uint)scene.RegionInfo.InternalEndPoint.Port; 81 uint port = (uint)scene.RegionInfo.InternalEndPoint.Port;
83 82
84 IPAddress listenIP = scene.RegionInfo.InternalEndPoint.Address; 83 IPAddress listenIP = scene.RegionInfo.InternalEndPoint.Address;
85 Initialise(listenIP, ref port, scene.RegionInfo.ProxyOffset, scene.RegionInfo.m_allow_alternate_ports, m_Config, scene.AuthenticateHandler); 84 Initialise(listenIP, ref port, scene.RegionInfo.ProxyOffset, m_Config, scene.AuthenticateHandler);
86 scene.RegionInfo.InternalEndPoint.Port = (int)port; 85 scene.RegionInfo.InternalEndPoint.Port = (int)port;
87 86
88 AddScene(scene); 87 AddScene(scene);
89 } 88 }
90 89
91 public void RemoveRegion(Scene scene) 90 public virtual void RemoveRegion(Scene scene)
92 { 91 {
93 Stop(); 92 Stop();
94 } 93 }
95 94
96 public void RegionLoaded(Scene scene) 95 public virtual void RegionLoaded(Scene scene)
97 { 96 {
98 Start(); 97 Start();
99 } 98 }
100 #endregion 99 #endregion
101 100
102 public void Initialise(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 101 public virtual void Initialise(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, IConfigSource configSource, AgentCircuitManager circuitManager)
103 { 102 {
104 m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager); 103 m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, configSource, circuitManager);
105 } 104 }
106 105
107 public void AddScene(IScene scene) 106 public virtual void AddScene(IScene scene)
108 { 107 {
109 m_udpServer.AddScene(scene); 108 m_udpServer.AddScene(scene);
110 109
@@ -223,22 +222,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
223 StatType.Pull, 222 StatType.Pull,
224 MeasuresOfInterest.None, 223 MeasuresOfInterest.None,
225 stat => stat.Value = m_udpServer.AverageReceiveTicksForLastSamplePeriod, 224 stat => stat.Value = m_udpServer.AverageReceiveTicksForLastSamplePeriod,
226// stat => 225// stat =>
227// stat.Value = Math.Round(m_udpServer.AverageReceiveTicksForLastSamplePeriod, 7), 226// stat.Value = Math.Round(m_udpServer.AverageReceiveTicksForLastSamplePeriod, 7),
228 StatVerbosity.Debug)); 227 StatVerbosity.Debug));
229 } 228 }
230 229
231 public bool HandlesRegion(Location x) 230 public virtual bool HandlesRegion(Location x)
232 { 231 {
233 return m_udpServer.HandlesRegion(x); 232 return m_udpServer.HandlesRegion(x);
234 } 233 }
235 234
236 public void Start() 235 public virtual void Start()
237 { 236 {
238 m_udpServer.Start(); 237 m_udpServer.Start();
239 } 238 }
240 239
241 public void Stop() 240 public virtual void Stop()
242 { 241 {
243 m_udpServer.Stop(); 242 m_udpServer.Stop();
244 } 243 }
@@ -257,7 +256,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
257 public const int MTU = 1400; 256 public const int MTU = 1400;
258 257
259 /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary> 258 /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary>
260 public int ClientLogoutsDueToNoReceives { get; private set; } 259 public int ClientLogoutsDueToNoReceives { get; protected set; }
261 260
262 /// <summary> 261 /// <summary>
263 /// Default packet debug level given to new clients 262 /// Default packet debug level given to new clients
@@ -273,7 +272,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
273 /// <summary>The measured resolution of Environment.TickCount</summary> 272 /// <summary>The measured resolution of Environment.TickCount</summary>
274 public readonly float TickCountResolution; 273 public readonly float TickCountResolution;
275 274
276 /// <summary>Number of prim updates to put on the queue each time the 275 /// <summary>Number of prim updates to put on the queue each time the
277 /// OnQueueEmpty event is triggered for updates</summary> 276 /// OnQueueEmpty event is triggered for updates</summary>
278 public readonly int PrimUpdatesPerCallback; 277 public readonly int PrimUpdatesPerCallback;
279 278
@@ -284,54 +283,53 @@ namespace OpenSim.Region.ClientStack.LindenUDP
284 /// <summary>Handlers for incoming packets</summary> 283 /// <summary>Handlers for incoming packets</summary>
285 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 284 //PacketEventDictionary packetEvents = new PacketEventDictionary();
286 /// <summary>Incoming packets that are awaiting handling</summary> 285 /// <summary>Incoming packets that are awaiting handling</summary>
287 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 286 //protected OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
287
288 protected OpenSim.Framework.BlockingQueue<IncomingPacket> packetInbox = new OpenSim.Framework.BlockingQueue<IncomingPacket>();
288 289
289 /// <summary>Bandwidth throttle for this UDP server</summary> 290 /// <summary>Bandwidth throttle for this UDP server</summary>
290 public TokenBucket Throttle { get; private set; } 291 public TokenBucket Throttle { get; protected set; }
291 292
292 /// <summary>Per client throttle rates enforced by this server</summary> 293 /// <summary>Per client throttle rates enforced by this server</summary>
293 /// <remarks> 294 /// <remarks>
294 /// If the total rate is non-zero, then this is the maximum total throttle setting that any client can ever have. 295 /// 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 /// 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 /// do get changed immediately). They do not need to sum to the total.
297 /// </remarks> 298 /// </remarks>
298 public ThrottleRates ThrottleRates { get; private set; } 299 public ThrottleRates ThrottleRates { get; protected set; }
299 300
300 /// <summary>Manages authentication for agent circuits</summary> 301 /// <summary>Manages authentication for agent circuits</summary>
301 private AgentCircuitManager m_circuitManager; 302 protected AgentCircuitManager m_circuitManager;
302 303
303 /// <summary>Reference to the scene this UDP server is attached to</summary> 304 /// <summary>Reference to the scene this UDP server is attached to</summary>
304 public Scene Scene { get; private set; } 305 public Scene Scene { get; protected set; }
305 306
306 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 307 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
307 private Location m_location; 308 protected Location m_location;
308 309
309 /// <summary>The size of the receive buffer for the UDP socket. This value 310 /// <summary>The size of the receive buffer for the UDP socket. This value
310 /// is passed up to the operating system and used in the system networking 311 /// is passed up to the operating system and used in the system networking
311 /// stack. Use zero to leave this value as the default</summary> 312 /// stack. Use zero to leave this value as the default</summary>
312 private int m_recvBufferSize; 313 protected int m_recvBufferSize;
313
314 /// <summary>Flag to process packets asynchronously or synchronously</summary>
315 private bool m_asyncPacketHandling;
316 314
317 /// <summary>Tracks whether or not a packet was sent each round so we know 315 /// <summary>Tracks whether or not a packet was sent each round so we know
318 /// whether or not to sleep</summary> 316 /// whether or not to sleep</summary>
319 private bool m_packetSent; 317 protected bool m_packetSent;
320 318
321 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> 319 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary>
322 private int m_elapsedMSSinceLastStatReport = 0; 320 protected int m_elapsedMSSinceLastStatReport = 0;
323 321
324 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> 322 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
325 private int m_tickLastOutgoingPacketHandler; 323 protected double m_tickLastOutgoingPacketHandler;
326 324
327 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> 325 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
328 private int m_elapsedMSOutgoingPacketHandler; 326 protected double m_elapsedMSOutgoingPacketHandler;
329 327
330 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> 328 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
331 private int m_elapsed100MSOutgoingPacketHandler; 329 protected int m_elapsed100MSOutgoingPacketHandler;
332 330
333 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> 331 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
334 private int m_elapsed500MSOutgoingPacketHandler; 332 protected int m_elapsed500MSOutgoingPacketHandler;
335 333
336 /// <summary>Flag to signal when clients should check for resends</summary> 334 /// <summary>Flag to signal when clients should check for resends</summary>
337 protected bool m_resendUnacked; 335 protected bool m_resendUnacked;
@@ -342,32 +340,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
342 /// <summary>Flag to signal when clients should send pings</summary> 340 /// <summary>Flag to signal when clients should send pings</summary>
343 protected bool m_sendPing; 341 protected bool m_sendPing;
344 342
345 /// <summary> 343 protected int m_animationSequenceNumber;
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 344
354 private Pool<IncomingPacket> m_incomingPacketPool; 345 public int NextAnimationSequenceNumber
346 {
347 get
348 {
349 m_animationSequenceNumber++;
350 if (m_animationSequenceNumber > 2147482624)
351 m_animationSequenceNumber = 1;
352 return m_animationSequenceNumber;
353 }
354 }
355
356 protected ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
357
358 protected Pool<IncomingPacket> m_incomingPacketPool;
355 359
356 /// <summary> 360 /// <summary>
357 /// Stat for number of packets in the main pool awaiting use. 361 /// Stat for number of packets in the main pool awaiting use.
358 /// </summary> 362 /// </summary>
359 private Stat m_poolCountStat; 363 protected Stat m_poolCountStat;
360 364
361 /// <summary> 365 /// <summary>
362 /// Stat for number of packets in the inbound packet pool awaiting use. 366 /// Stat for number of packets in the inbound packet pool awaiting use.
363 /// </summary> 367 /// </summary>
364 private Stat m_incomingPacketPoolStat; 368 protected Stat m_incomingPacketPoolStat;
365 369
366 private int m_defaultRTO = 0; 370 protected int m_defaultRTO = 0;
367 private int m_maxRTO = 0; 371 protected int m_maxRTO = 0;
368 private int m_ackTimeout = 0; 372 protected int m_ackTimeout = 0;
369 private int m_pausedAckTimeout = 0; 373 protected int m_pausedAckTimeout = 0;
370 private bool m_disableFacelights = false; 374 protected bool m_disableFacelights = false;
371 375
372 public Socket Server { get { return null; } } 376 public Socket Server { get { return null; } }
373 377
@@ -389,28 +393,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
389 /// <summary> 393 /// <summary>
390 /// Record how many inbound packets could not be recognized as LLUDP packets. 394 /// Record how many inbound packets could not be recognized as LLUDP packets.
391 /// </summary> 395 /// </summary>
392 public int IncomingMalformedPacketCount { get; private set; } 396 public int IncomingMalformedPacketCount { get; protected set; }
393 397
394 /// <summary> 398 /// <summary>
395 /// Record how many inbound packets could not be associated with a simulator circuit. 399 /// Record how many inbound packets could not be associated with a simulator circuit.
396 /// </summary> 400 /// </summary>
397 public int IncomingOrphanedPacketCount { get; private set; } 401 public int IncomingOrphanedPacketCount { get; protected set; }
398 402
399 /// <summary> 403 /// <summary>
400 /// Record current outgoing client for monitoring purposes. 404 /// Record current outgoing client for monitoring purposes.
401 /// </summary> 405 /// </summary>
402 private IClientAPI m_currentOutgoingClient; 406 protected IClientAPI m_currentOutgoingClient;
403 407
404 /// <summary> 408 /// <summary>
405 /// Recording current incoming client for monitoring purposes. 409 /// Recording current incoming client for monitoring purposes.
406 /// </summary> 410 /// </summary>
407 private IClientAPI m_currentIncomingClient; 411 protected IClientAPI m_currentIncomingClient;
408 412
409 /// <summary> 413 /// <summary>
410 /// Queue some low priority but potentially high volume async requests so that they don't overwhelm available 414 /// Queue some low priority but potentially high volume async requests so that they don't overwhelm available
411 /// threadpool threads. 415 /// threadpool threads.
412 /// </summary> 416 /// </summary>
413 public JobEngine IpahEngine { get; private set; } 417// public JobEngine IpahEngine { get; protected set; }
414 418
415 /// <summary> 419 /// <summary>
416 /// Run queue empty processing within a single persistent thread. 420 /// Run queue empty processing within a single persistent thread.
@@ -420,27 +424,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP
420 /// connection schedule its own job in the threadpool which causes performance problems when there are many 424 /// connection schedule its own job in the threadpool which causes performance problems when there are many
421 /// connections. 425 /// connections.
422 /// </remarks> 426 /// </remarks>
423 public JobEngine OqrEngine { get; private set; } 427 public JobEngine OqrEngine { get; protected set; }
424 428
425 public LLUDPServer( 429 public LLUDPServer(
426 IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, 430 IPAddress listenIP, ref uint port, int proxyPortOffsetParm,
427 IConfigSource configSource, AgentCircuitManager circuitManager) 431 IConfigSource configSource, AgentCircuitManager circuitManager)
428 : base(listenIP, (int)port) 432 : base(listenIP, (int)port)
429 { 433 {
430 #region Environment.TickCount Measurement 434 #region Environment.TickCount Measurement
431 435
436 // Update the port with the one we actually got
437 port = (uint)Port;
438
432 // Measure the resolution of Environment.TickCount 439 // Measure the resolution of Environment.TickCount
433 TickCountResolution = 0f; 440 TickCountResolution = 0f;
434 for (int i = 0; i < 5; i++) 441 for (int i = 0; i < 10; i++)
435 { 442 {
436 int start = Environment.TickCount; 443 int start = Environment.TickCount;
437 int now = start; 444 int now = start;
438 while (now == start) 445 while (now == start)
439 now = Environment.TickCount; 446 now = Environment.TickCount;
440 TickCountResolution += (float)(now - start) * 0.2f; 447 TickCountResolution += (float)(now - start);
448 }
449 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution * 0.1f + "ms");
450
451 TickCountResolution = 0f;
452 for (int i = 0; i < 100; i++)
453 {
454 double start = Util.GetTimeStampMS();
455 double now = start;
456 while (now == start)
457 now = Util.GetTimeStampMS();
458 TickCountResolution += (float)((now - start));
441 } 459 }
442 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms"); 460
443 TickCountResolution = (float)Math.Ceiling(TickCountResolution); 461 TickCountResolution = (float)Math.Round(TickCountResolution * 0.01f,6,MidpointRounding.AwayFromZero);
462 m_log.Info("[LLUDPSERVER]: Average Util.GetTimeStampMS resolution: " + TickCountResolution + "ms");
444 463
445 #endregion Environment.TickCount Measurement 464 #endregion Environment.TickCount Measurement
446 465
@@ -451,7 +470,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
451 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 470 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
452 if (config != null) 471 if (config != null)
453 { 472 {
454 m_asyncPacketHandling = config.GetBoolean("async_packet_handling", true);
455 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); 473 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
456 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); 474 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
457 475
@@ -494,24 +512,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
494 } 512 }
495 #endregion BinaryStats 513 #endregion BinaryStats
496 514
497 // FIXME: Can't add info here because don't know scene yet. 515 Throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps * 10e-3f);
498// m_throttle
499// = new TokenBucket(
500// string.Format("server throttle bucket for {0}", Scene.Name), null, sceneThrottleBps);
501
502 Throttle = new TokenBucket("server throttle bucket", null, 0, sceneThrottleBps);
503
504 ThrottleRates = new ThrottleRates(configSource); 516 ThrottleRates = new ThrottleRates(configSource);
505 517
506 if (usePools) 518 Random rnd = new Random(Util.EnvironmentTickCount());
507 EnablePools(); 519 m_animationSequenceNumber = rnd.Next(11474826);
520
521// if (usePools)
522// EnablePools();
523 base.DisablePools();
508 } 524 }
509 525
510 public void Start() 526 public void Start()
511 { 527 {
512 StartInbound(); 528 StartInbound();
513 StartOutbound(); 529 StartOutbound();
514 IpahEngine.Start(); 530// IpahEngine.Start();
515 OqrEngine.Start(); 531 OqrEngine.Start();
516 532
517 m_elapsedMSSinceLastStatReport = Environment.TickCount; 533 m_elapsedMSSinceLastStatReport = Environment.TickCount;
@@ -520,10 +536,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
520 public void StartInbound() 536 public void StartInbound()
521 { 537 {
522 m_log.InfoFormat( 538 m_log.InfoFormat(
523 "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", 539 "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server");
524 m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools);
525 540
526 base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); 541 base.StartInbound(m_recvBufferSize);
527 542
528 // This thread will process the packets received that are placed on the packetInbox 543 // This thread will process the packets received that are placed on the packetInbox
529 WorkManager.StartThread( 544 WorkManager.StartThread(
@@ -557,7 +572,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
557 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + Scene.Name); 572 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + Scene.Name);
558 base.StopOutbound(); 573 base.StopOutbound();
559 base.StopInbound(); 574 base.StopInbound();
560 IpahEngine.Stop(); 575// IpahEngine.Stop();
561 OqrEngine.Stop(); 576 OqrEngine.Stop();
562 } 577 }
563 578
@@ -642,7 +657,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
642 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. 657 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
643 /// </summary> 658 /// </summary>
644 /// <returns></returns> 659 /// <returns></returns>
645 private string GetWatchdogIncomingAlarmData() 660 protected string GetWatchdogIncomingAlarmData()
646 { 661 {
647 return string.Format( 662 return string.Format(
648 "Client is {0}", 663 "Client is {0}",
@@ -653,7 +668,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
653 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. 668 /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging.
654 /// </summary> 669 /// </summary>
655 /// <returns></returns> 670 /// <returns></returns>
656 private string GetWatchdogOutgoingAlarmData() 671 protected string GetWatchdogOutgoingAlarmData()
657 { 672 {
658 return string.Format( 673 return string.Format(
659 "Client is {0}", 674 "Client is {0}",
@@ -676,15 +691,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
676 691
677 Scene = (Scene)scene; 692 Scene = (Scene)scene;
678 m_location = new Location(Scene.RegionInfo.RegionHandle); 693 m_location = new Location(Scene.RegionInfo.RegionHandle);
679 694/*
680 IpahEngine 695 IpahEngine
681 = new JobEngine( 696 = new JobEngine(
682 string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name), 697 string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name),
683 "INCOMING PACKET ASYNC HANDLING ENGINE"); 698 "INCOMING PACKET ASYNC HANDLING ENGINE");
684 699*/
685 OqrEngine 700 OqrEngine
686 = new JobEngine( 701 = new JobEngine(
687 string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name), 702 string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name),
688 "OUTGOING QUEUE REFILL ENGINE"); 703 "OUTGOING QUEUE REFILL ENGINE");
689 704
690 StatsManager.RegisterStat( 705 StatsManager.RegisterStat(
@@ -697,7 +712,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
697 scene.Name, 712 scene.Name,
698 StatType.Pull, 713 StatType.Pull,
699 MeasuresOfInterest.AverageChangeOverTime, 714 MeasuresOfInterest.AverageChangeOverTime,
700 stat => stat.Value = packetInbox.Count, 715 stat => stat.Value = packetInbox.Count(),
701 StatVerbosity.Debug)); 716 StatVerbosity.Debug));
702 717
703 // XXX: These stats are also pool stats but we register them separately since they are currently not 718 // XXX: These stats are also pool stats but we register them separately since they are currently not
@@ -710,9 +725,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
710 "clientstack", 725 "clientstack",
711 Scene.Name, 726 Scene.Name,
712 StatType.Pull, 727 StatType.Pull,
713 stat => 728 stat =>
714 { PercentageStat pstat = (PercentageStat)stat; 729 { PercentageStat pstat = (PercentageStat)stat;
715 pstat.Consequent = PacketPool.Instance.PacketsRequested; 730 pstat.Consequent = PacketPool.Instance.PacketsRequested;
716 pstat.Antecedent = PacketPool.Instance.PacketsReused; }, 731 pstat.Antecedent = PacketPool.Instance.PacketsReused; },
717 StatVerbosity.Debug)); 732 StatVerbosity.Debug));
718 733
@@ -725,8 +740,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
725 Scene.Name, 740 Scene.Name,
726 StatType.Pull, 741 StatType.Pull,
727 stat => 742 stat =>
728 { PercentageStat pstat = (PercentageStat)stat; 743 { PercentageStat pstat = (PercentageStat)stat;
729 pstat.Consequent = PacketPool.Instance.BlocksRequested; 744 pstat.Consequent = PacketPool.Instance.BlocksRequested;
730 pstat.Antecedent = PacketPool.Instance.BlocksReused; }, 745 pstat.Antecedent = PacketPool.Instance.BlocksReused; },
731 StatVerbosity.Debug)); 746 StatVerbosity.Debug));
732 747
@@ -766,7 +781,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
766 MeasuresOfInterest.AverageChangeOverTime, 781 MeasuresOfInterest.AverageChangeOverTime,
767 stat => stat.Value = GetTotalQueuedOutgoingPackets(), 782 stat => stat.Value = GetTotalQueuedOutgoingPackets(),
768 StatVerbosity.Info)); 783 StatVerbosity.Info));
769 784/*
770 StatsManager.RegisterStat( 785 StatsManager.RegisterStat(
771 new Stat( 786 new Stat(
772 "IncomingPacketAsyncRequestsWaiting", 787 "IncomingPacketAsyncRequestsWaiting",
@@ -779,7 +794,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
779 MeasuresOfInterest.None, 794 MeasuresOfInterest.None,
780 stat => stat.Value = IpahEngine.JobsWaiting, 795 stat => stat.Value = IpahEngine.JobsWaiting,
781 StatVerbosity.Debug)); 796 StatVerbosity.Debug));
782 797*/
783 StatsManager.RegisterStat( 798 StatsManager.RegisterStat(
784 new Stat( 799 new Stat(
785 "OQRERequestsWaiting", 800 "OQRERequestsWaiting",
@@ -792,14 +807,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
792 MeasuresOfInterest.None, 807 MeasuresOfInterest.None,
793 stat => stat.Value = OqrEngine.JobsWaiting, 808 stat => stat.Value = OqrEngine.JobsWaiting,
794 StatVerbosity.Debug)); 809 StatVerbosity.Debug));
795 810
796 // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by 811 // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by
797 // scene name 812 // scene name
798 if (UsePools) 813 if (UsePools)
799 EnablePoolStats(); 814 EnablePoolStats();
800 815
816
801 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); 817 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this);
802 commands.Register(); 818 commands.Register();
819
803 } 820 }
804 821
805 public bool HandlesRegion(Location x) 822 public bool HandlesRegion(Location x)
@@ -906,9 +923,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
906 } 923 }
907 924
908 PacketPool.Instance.ReturnPacket(packet); 925 PacketPool.Instance.ReturnPacket(packet);
909
910 if (packetQueued)
911 m_dataPresentEvent.Set();
912 } 926 }
913 927
914 /// <summary> 928 /// <summary>
@@ -969,8 +983,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
969 bufferSize = dataLength; 983 bufferSize = dataLength;
970 buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); 984 buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
971 985
972 // m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" + 986 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
973 // type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet"); 987 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
974 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 988 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
975 } 989 }
976 } 990 }
@@ -979,35 +993,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
979 993
980 #region Queue or Send 994 #region Queue or Send
981 995
996 bool highPriority = false;
997
998 if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
999 {
1000 category = (ThrottleOutPacketType)((int)category & 127);
1001 highPriority = true;
1002 }
1003
982 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); 1004 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
983 1005
984 // If we were not provided a method for handling unacked, use the UDPServer default method 1006 // If we were not provided a method for handling unacked, use the UDPServer default method
985 if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0) 1007 if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0)
986 outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); 1008 outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
987 1009
988 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will 1010 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
989 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object 1011 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object
990 // packet so that it isn't sent before a queued update packet. 1012 // packet so that it isn't sent before a queued update packet.
991 bool forceQueue = (type == PacketType.KillObject);
992 1013
993// if (type == PacketType.ImprovedTerseObjectUpdate) 1014 bool requestQueue = type == PacketType.KillObject;
994// { 1015 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority))
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 { 1016 {
1003 SendPacketFinal(outgoingPacket); 1017 SendPacketFinal(outgoingPacket);
1004 return true; 1018 return true;
1005 } 1019 }
1006 else 1020
1007 { 1021 return false;
1008 return false;
1009 }
1010// }
1011 1022
1012 #endregion Queue or Send 1023 #endregion Queue or Send
1013 } 1024 }
@@ -1048,6 +1059,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1048 pc.PingID.OldestUnacked = 0; 1059 pc.PingID.OldestUnacked = 0;
1049 1060
1050 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null); 1061 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null);
1062 udpClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount();
1051 } 1063 }
1052 1064
1053 public void CompletePing(LLUDPClient udpClient, byte pingID) 1065 public void CompletePing(LLUDPClient udpClient, byte pingID)
@@ -1145,7 +1157,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1145 int dataLength = buffer.DataLength; 1157 int dataLength = buffer.DataLength;
1146 1158
1147 // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here 1159 // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here
1148 if (!isZerocoded) 1160 if (!isZerocoded && !isResend && outgoingPacket.UnackedMethod == null)
1149 { 1161 {
1150 // Keep appending ACKs until there is no room left in the buffer or there are 1162 // Keep appending ACKs until there is no room left in the buffer or there are
1151 // no more ACKs to append 1163 // no more ACKs to append
@@ -1180,7 +1192,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1180 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); 1192 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
1181 outgoingPacket.SequenceNumber = sequenceNumber; 1193 outgoingPacket.SequenceNumber = sequenceNumber;
1182 1194
1183 if (udpClient.ProcessUnackedSends && isReliable) 1195 if (isReliable)
1184 { 1196 {
1185 // Add this packet to the list of ACK responses we are waiting on from the server 1197 // Add this packet to the list of ACK responses we are waiting on from the server
1186 udpClient.NeedAcks.Add(outgoingPacket); 1198 udpClient.NeedAcks.Add(outgoingPacket);
@@ -1210,13 +1222,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1210 outgoingPacket.SequenceNumber, isReliable, isResend, udpClient.AgentID, Scene.Name); 1222 outgoingPacket.SequenceNumber, isReliable, isResend, udpClient.AgentID, Scene.Name);
1211 1223
1212 // Put the UDP payload on the wire 1224 // Put the UDP payload on the wire
1213 AsyncBeginSend(buffer); 1225// AsyncBeginSend(buffer);
1226 SyncSend(buffer);
1214 1227
1215 // Keep track of when this packet was sent out (right now) 1228 // Keep track of when this packet was sent out (right now)
1216 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; 1229 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
1217 } 1230 }
1218 1231
1219 private void RecordMalformedInboundPacket(IPEndPoint endPoint) 1232 protected void RecordMalformedInboundPacket(IPEndPoint endPoint)
1220 { 1233 {
1221// if (m_malformedCount < 100) 1234// if (m_malformedCount < 100)
1222// m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 1235// m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
@@ -1225,7 +1238,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1225 1238
1226 if ((IncomingMalformedPacketCount % 10000) == 0) 1239 if ((IncomingMalformedPacketCount % 10000) == 0)
1227 m_log.WarnFormat( 1240 m_log.WarnFormat(
1228 "[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack. Last was from {1}", 1241 "[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack. Last was from {1}",
1229 IncomingMalformedPacketCount, endPoint); 1242 IncomingMalformedPacketCount, endPoint);
1230 } 1243 }
1231 1244
@@ -1311,35 +1324,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1311 1324
1312 #region Packet to Client Mapping 1325 #region Packet to Client Mapping
1313 1326
1314 // UseCircuitCode handling 1327 // If there is already a client for this endpoint, don't process UseCircuitCode
1315 if (packet.Type == PacketType.UseCircuitCode) 1328 IClientAPI client = null;
1329 if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1316 { 1330 {
1317 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1331 // UseCircuitCode handling
1318 // buffer. 1332 if (packet.Type == PacketType.UseCircuitCode)
1319 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1333 {
1334 // And if there is a UseCircuitCode pending, also drop it
1335 lock (m_pendingCache)
1336 {
1337 if (m_pendingCache.Contains(endPoint))
1338 return;
1320 1339
1321 Util.FireAndForget(HandleUseCircuitCode, array, "LLUDPServer.HandleUseCircuitCode"); 1340 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
1341 }
1322 1342
1323 return; 1343 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1344 // buffer.
1345 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1346
1347 Util.FireAndForget(HandleUseCircuitCode, array);
1348
1349 return;
1350 }
1324 } 1351 }
1325 else if (packet.Type == PacketType.CompleteAgentMovement) 1352
1353 // If this is a pending connection, enqueue, don't process yet
1354 lock (m_pendingCache)
1326 { 1355 {
1327 // Send ack straight away to let the viewer know that we got it. 1356 Queue<UDPPacketBuffer> queue;
1328 SendAckImmediate(endPoint, packet.Header.Sequence); 1357 if (m_pendingCache.TryGetValue(endPoint, out queue))
1358 {
1359 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
1360 queue.Enqueue(buffer);
1361 return;
1362 }
1329 1363
1330 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1364/*
1331 // buffer. 1365 else if (packet.Type == PacketType.CompleteAgentMovement)
1332 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1366 {
1367 // Send ack straight away to let the viewer know that we got it.
1368 SendAckImmediate(endPoint, packet.Header.Sequence);
1333 1369
1334 Util.FireAndForget( 1370 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1335 HandleCompleteMovementIntoRegion, array, "LLUDPServer.HandleCompleteMovementIntoRegion"); 1371 // buffer.
1372 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1336 1373
1337 return; 1374 Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
1375
1376 return;
1377 }
1378 */
1338 } 1379 }
1339 1380
1340 // Determine which agent this packet came from 1381 // Determine which agent this packet came from
1341 IClientAPI client; 1382 if (client == null || !(client is LLClientView))
1342 if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1343 { 1383 {
1344 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1384 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
1345 1385
@@ -1347,7 +1387,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1347 1387
1348 if ((IncomingOrphanedPacketCount % 10000) == 0) 1388 if ((IncomingOrphanedPacketCount % 10000) == 0)
1349 m_log.WarnFormat( 1389 m_log.WarnFormat(
1350 "[LLUDPSERVER]: Received {0} orphaned packets so far. Last was from {1}", 1390 "[LLUDPSERVER]: Received {0} orphaned packets so far. Last was from {1}",
1351 IncomingOrphanedPacketCount, endPoint); 1391 IncomingOrphanedPacketCount, endPoint);
1352 1392
1353 return; 1393 return;
@@ -1356,7 +1396,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1356 udpClient = ((LLClientView)client).UDPClient; 1396 udpClient = ((LLClientView)client).UDPClient;
1357 1397
1358 if (!udpClient.IsConnected) 1398 if (!udpClient.IsConnected)
1399 {
1400 m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + Scene.RegionInfo.RegionName);
1359 return; 1401 return;
1402 }
1360 1403
1361 #endregion Packet to Client Mapping 1404 #endregion Packet to Client Mapping
1362 1405
@@ -1368,37 +1411,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1368 1411
1369 #region ACK Receiving 1412 #region ACK Receiving
1370 1413
1371 if (udpClient.ProcessUnackedSends) 1414 // Handle appended ACKs
1415 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
1372 { 1416 {
1373 // Handle appended ACKs 1417 // m_log.DebugFormat(
1374 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 1418 // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1375 { 1419 // packet.Header.AckList.Length, client.Name, m_scene.Name);
1376 // m_log.DebugFormat(
1377 // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1378 // packet.Header.AckList.Length, client.Name, m_scene.Name);
1379 1420
1380 for (int i = 0; i < packet.Header.AckList.Length; i++) 1421 for (int i = 0; i < packet.Header.AckList.Length; i++)
1381 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 1422 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
1382 } 1423 }
1383 1424
1384 // Handle PacketAck packets 1425 // Handle PacketAck packets
1385 if (packet.Type == PacketType.PacketAck) 1426 if (packet.Type == PacketType.PacketAck)
1386 { 1427 {
1387 PacketAckPacket ackPacket = (PacketAckPacket)packet; 1428 PacketAckPacket ackPacket = (PacketAckPacket)packet;
1388 1429
1389 // m_log.DebugFormat( 1430 // m_log.DebugFormat(
1390 // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", 1431 // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
1391 // ackPacket.Packets.Length, client.Name, m_scene.Name); 1432 // ackPacket.Packets.Length, client.Name, m_scene.Name);
1392 1433
1393 for (int i = 0; i < ackPacket.Packets.Length; i++) 1434 for (int i = 0; i < ackPacket.Packets.Length; i++)
1394 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); 1435 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
1395 1436
1396 // We don't need to do anything else with PacketAck packets 1437 // We don't need to do anything else with PacketAck packets
1397 return;
1398 }
1399 }
1400 else if (packet.Type == PacketType.PacketAck)
1401 {
1402 return; 1438 return;
1403 } 1439 }
1404 1440
@@ -1442,7 +1478,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1442 { 1478 {
1443 if (packet.Header.Resent) 1479 if (packet.Header.Resent)
1444 m_log.DebugFormat( 1480 m_log.DebugFormat(
1445 "[LLUDPSERVER]: Received a resend of already processed packet #{0}, type {1} from {2}", 1481 "[LLUDPSERVER]: Received a resend of already processed packet #{0}, type {1} from {2}",
1446 packet.Header.Sequence, packet.Type, client.Name); 1482 packet.Header.Sequence, packet.Type, client.Name);
1447 else 1483 else
1448 m_log.WarnFormat( 1484 m_log.WarnFormat(
@@ -1459,24 +1495,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1459 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1495 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1460 #endregion BinaryStats 1496 #endregion BinaryStats
1461 1497
1462 if (packet.Type == PacketType.AgentUpdate)
1463 {
1464 if (DiscardInboundAgentUpdates)
1465 return;
1466 1498
1467 ((LLClientView)client).TotalAgentUpdates++; 1499//AgentUpdate removed from here
1468 1500
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 1501
1481 #region Ping Check Handling 1502 #region Ping Check Handling
1482 1503
@@ -1497,7 +1518,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1497 } 1518 }
1498 else if (packet.Type == PacketType.CompletePingCheck) 1519 else if (packet.Type == PacketType.CompletePingCheck)
1499 { 1520 {
1500 // We don't currently track client ping times 1521 int t = Util.EnvironmentTickCountSubtract(udpClient.m_lastStartpingTimeMS);
1522 int c = udpClient.m_pingMS;
1523 c = 800 * c + 200 * t;
1524 c /= 1000;
1525 udpClient.m_pingMS = c;
1501 return; 1526 return;
1502 } 1527 }
1503 1528
@@ -1517,7 +1542,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1517 incomingPacket = new IncomingPacket((LLClientView)client, packet); 1542 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1518 } 1543 }
1519 1544
1520 packetInbox.Enqueue(incomingPacket); 1545// if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1546// incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1547 if (incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1548 packetInbox.PriorityEnqueue(incomingPacket);
1549 else
1550 packetInbox.Enqueue(incomingPacket);
1551
1521 } 1552 }
1522 1553
1523 #region BinaryStats 1554 #region BinaryStats
@@ -1627,14 +1658,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1627 1658
1628 #endregion BinaryStats 1659 #endregion BinaryStats
1629 1660
1630 private void HandleUseCircuitCode(object o) 1661 protected void HandleUseCircuitCode(object o)
1631 { 1662 {
1632 IPEndPoint endPoint = null; 1663 IPEndPoint endPoint = null;
1633 IClientAPI client = null; 1664 IClientAPI client = null;
1634 1665
1635 try 1666 try
1636 { 1667 {
1637 // DateTime startTime = DateTime.Now; 1668// DateTime startTime = DateTime.Now;
1638 object[] array = (object[])o; 1669 object[] array = (object[])o;
1639 endPoint = (IPEndPoint)array[0]; 1670 endPoint = (IPEndPoint)array[0];
1640 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1671 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
@@ -1642,10 +1673,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1642 m_log.DebugFormat( 1673 m_log.DebugFormat(
1643 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", 1674 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
1644 uccp.CircuitCode.Code, Scene.RegionInfo.RegionName, endPoint); 1675 uccp.CircuitCode.Code, Scene.RegionInfo.RegionName, endPoint);
1645 1676
1646 AuthenticateResponse sessionInfo; 1677 AuthenticateResponse sessionInfo;
1647 if (IsClientAuthorized(uccp, out sessionInfo)) 1678 if (IsClientAuthorized(uccp, out sessionInfo))
1648 { 1679 {
1680 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1681
1649 // Begin the process of adding the client to the simulator 1682 // Begin the process of adding the client to the simulator
1650 client 1683 client
1651 = AddClient( 1684 = AddClient(
@@ -1654,20 +1687,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1654 uccp.CircuitCode.SessionID, 1687 uccp.CircuitCode.SessionID,
1655 endPoint, 1688 endPoint,
1656 sessionInfo); 1689 sessionInfo);
1657 1690
1691 // This will be true if the client is new, e.g. not
1692 // an existing child agent, and there is no circuit data
1693 if (client != null && aCircuit == null)
1694 {
1695 Scene.CloseAgent(client.AgentId, true);
1696 return;
1697 }
1698
1699 // Now we know we can handle more data
1700 Thread.Sleep(200);
1701
1702 // Obtain the pending queue and remove it from the cache
1703 Queue<UDPPacketBuffer> queue = null;
1704
1705 lock (m_pendingCache)
1706 {
1707 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1708 {
1709 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1710 return;
1711
1712 }
1713 m_pendingCache.Remove(endPoint);
1714 }
1715
1716 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1717
1718 // Reinject queued packets
1719 while (queue.Count > 0)
1720 {
1721 UDPPacketBuffer buf = queue.Dequeue();
1722 PacketReceived(buf);
1723 }
1724
1725 queue = null;
1726
1658 // Send ack straight away to let the viewer know that the connection is active. 1727 // Send ack straight away to let the viewer know that the connection is active.
1659 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1728 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1660 // circuit code to the existing child agent. This is not particularly obvious. 1729 // circuit code to the existing child agent. This is not particularly obvious.
1661 SendAckImmediate(endPoint, uccp.Header.Sequence); 1730 SendAckImmediate(endPoint, uccp.Header.Sequence);
1662 1731
1663 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1732 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1664 if (client != null) 1733 if (client != null)
1665 { 1734 {
1666 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1667 bool tp = (aCircuit.teleportFlags > 0); 1735 bool tp = (aCircuit.teleportFlags > 0);
1668 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from 1736 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from
1669 if (!tp && !client.SceneAgent.SentInitialDataToClient) 1737 if (!tp)
1670 client.SceneAgent.SendInitialDataToClient(); 1738 client.SceneAgent.SendInitialDataToMe();
1671 } 1739 }
1672 } 1740 }
1673 else 1741 else
@@ -1675,11 +1743,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1675 // Don't create clients for unauthorized requesters. 1743 // Don't create clients for unauthorized requesters.
1676 m_log.WarnFormat( 1744 m_log.WarnFormat(
1677 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1745 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1746
1678 uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1747 uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1748
1749 lock (m_pendingCache)
1750 m_pendingCache.Remove(endPoint);
1679 } 1751 }
1680 1752
1681 // m_log.DebugFormat( 1753 // m_log.DebugFormat(
1682 // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", 1754 // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms",
1683 // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); 1755 // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds);
1684 1756
1685 } 1757 }
@@ -1694,8 +1766,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1694 e.StackTrace); 1766 e.StackTrace);
1695 } 1767 }
1696 } 1768 }
1697 1769/*
1698 private void HandleCompleteMovementIntoRegion(object o) 1770 protected void HandleCompleteMovementIntoRegion(object o)
1699 { 1771 {
1700 IPEndPoint endPoint = null; 1772 IPEndPoint endPoint = null;
1701 IClientAPI client = null; 1773 IClientAPI client = null;
@@ -1711,9 +1783,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1711 1783
1712 // Determine which agent this packet came from 1784 // 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 1785 // 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 1786 // 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 1787 // 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 1788 // packets asynchronously, we need to account for this thread proceeding more quickly than the
1717 // UseCircuitCode thread. 1789 // UseCircuitCode thread.
1718 int count = 40; 1790 int count = 40;
1719 while (count-- > 0) 1791 while (count-- > 0)
@@ -1735,7 +1807,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1735 // manager but the SceneAgent has not yet been set in Scene.AddNewAgent(). If we are too 1807 // 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 1808 // eager, then the new ScenePresence may not have registered a listener for this messsage
1737 // before we try to process it. 1809 // 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 1810 // XXX: A better long term fix may be to add the SceneAgent before the client is added to
1739 // the client manager 1811 // the client manager
1740 m_log.DebugFormat( 1812 m_log.DebugFormat(
1741 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.", 1813 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.",
@@ -1749,7 +1821,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1749 else 1821 else
1750 { 1822 {
1751 m_log.DebugFormat( 1823 m_log.DebugFormat(
1752 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.", 1824 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.",
1753 endPoint, Scene.Name); 1825 endPoint, Scene.Name);
1754 } 1826 }
1755 1827
@@ -1804,6 +1876,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1804 e.StackTrace); 1876 e.StackTrace);
1805 } 1877 }
1806 } 1878 }
1879*/
1807 1880
1808 /// <summary> 1881 /// <summary>
1809 /// Send an ack immediately to the given endpoint. 1882 /// Send an ack immediately to the given endpoint.
@@ -1814,7 +1887,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1814 /// </remarks> 1887 /// </remarks>
1815 /// <param name="remoteEndpoint"></param> 1888 /// <param name="remoteEndpoint"></param>
1816 /// <param name="sequenceNumber"></param> 1889 /// <param name="sequenceNumber"></param>
1817 private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber) 1890 protected void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber)
1818 { 1891 {
1819 PacketAckPacket ack = new PacketAckPacket(); 1892 PacketAckPacket ack = new PacketAckPacket();
1820 ack.Header.Reliable = false; 1893 ack.Header.Reliable = false;
@@ -1835,10 +1908,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1835 1908
1836 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); 1909 Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length);
1837 1910
1838 AsyncBeginSend(buffer); 1911// AsyncBeginSend(buffer);
1912 SyncSend(buffer);
1839 } 1913 }
1840 1914
1841 private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) 1915 protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo)
1842 { 1916 {
1843 UUID agentID = useCircuitCode.CircuitCode.ID; 1917 UUID agentID = useCircuitCode.CircuitCode.ID;
1844 UUID sessionID = useCircuitCode.CircuitCode.SessionID; 1918 UUID sessionID = useCircuitCode.CircuitCode.SessionID;
@@ -1861,6 +1935,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1861 uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) 1935 uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
1862 { 1936 {
1863 IClientAPI client = null; 1937 IClientAPI client = null;
1938 bool createNew = false;
1864 1939
1865 // We currently synchronize this code across the whole scene to avoid issues such as 1940 // We currently synchronize this code across the whole scene to avoid issues such as
1866 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done 1941 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
@@ -1869,14 +1944,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1869 { 1944 {
1870 if (!Scene.TryGetClient(agentID, out client)) 1945 if (!Scene.TryGetClient(agentID, out client))
1871 { 1946 {
1947 createNew = true;
1948 }
1949 else
1950 {
1951 if (client.SceneAgent == null)
1952 {
1953 Scene.CloseAgent(agentID, true);
1954 createNew = true;
1955 }
1956 }
1957
1958 if (createNew)
1959 {
1872 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1960 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1873 1961
1962
1874 client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1963 client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1875 client.OnLogout += LogoutHandler; 1964 client.OnLogout += LogoutHandler;
1876 client.DebugPacketLevel = DefaultClientPacketDebugLevel; 1965 client.DebugPacketLevel = DefaultClientPacketDebugLevel;
1877 1966
1878 ((LLClientView)client).DisableFacelights = m_disableFacelights; 1967 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1879 1968
1880 client.Start(); 1969 client.Start();
1881 } 1970 }
1882 } 1971 }
@@ -1893,56 +1982,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1893 /// </remarks> 1982 /// </remarks>
1894 /// <param name='client'></param> 1983 /// <param name='client'></param>
1895 /// <param name='timeoutTicks'></param> 1984 /// <param name='timeoutTicks'></param>
1896 private void DeactivateClientDueToTimeout(LLClientView client, int timeoutTicks) 1985 protected void DeactivateClientDueToTimeout(LLClientView client, int timeoutTicks)
1897 { 1986 {
1898 lock (client.CloseSyncLock) 1987 lock (client.CloseSyncLock)
1899 { 1988 {
1900 ClientLogoutsDueToNoReceives++; 1989 ClientLogoutsDueToNoReceives++;
1901 1990
1902 m_log.WarnFormat( 1991 if (client.SceneAgent != null)
1903 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", 1992 {
1904 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name); 1993 m_log.WarnFormat(
1905 1994 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
1906 if (!client.SceneAgent.IsChildAgent) 1995 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name);
1907 client.Kick("Simulator logged you out due to connection timeout."); 1996
1997 if (!client.SceneAgent.IsChildAgent)
1998 client.Kick("Simulator logged you out due to connection timeout.");
1999 }
1908 } 2000 }
1909 2001
1910 Scene.CloseAgent(client.AgentId, true); 2002 if (!Scene.CloseAgent(client.AgentId, true))
2003 client.Close(true,true);
1911 } 2004 }
1912 2005
1913 private void IncomingPacketHandler() 2006 protected void IncomingPacketHandler()
1914 { 2007 {
1915 Thread.CurrentThread.Priority = ThreadPriority.Highest; 2008 Thread.CurrentThread.Priority = ThreadPriority.Highest;
1916 2009 IncomingPacket incomingPacket;
1917 // Set this culture for the thread that incoming packets are received 2010 // Set this culture for the thread that incoming packets are received
1918 // on to en-US to avoid number parsing issues 2011 // on to en-US to avoid number parsing issues
1919 Culture.SetCurrentCulture(); 2012 Culture.SetCurrentCulture();
1920 2013
1921 while (IsRunningInbound) 2014 while (IsRunningInbound)
1922 { 2015 {
2016 Scene.ThreadAlive(1);
1923 try 2017 try
1924 { 2018 {
1925 IncomingPacket incomingPacket = null; 2019 incomingPacket = packetInbox.Dequeue(250);
1926
1927 /*
1928 // HACK: This is a test to try and rate limit packet handling on Mono.
1929 // If it works, a more elegant solution can be devised
1930 if (Util.FireAndForgetCount() < 2)
1931 {
1932 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping");
1933 Thread.Sleep(30);
1934 }
1935 */
1936 2020
1937 if (packetInbox.Dequeue(100, ref incomingPacket)) 2021 if (incomingPacket != null && IsRunningInbound)
1938 { 2022 {
1939 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); 2023 ProcessInPacket(incomingPacket);
1940 2024
1941 if (UsePools) 2025 if (UsePools)
2026 {
2027 incomingPacket.Client = null;
1942 m_incomingPacketPool.ReturnObject(incomingPacket); 2028 m_incomingPacketPool.ReturnObject(incomingPacket);
2029 }
2030 incomingPacket = null;
1943 } 2031 }
1944 } 2032 }
1945 catch (Exception ex) 2033 catch(Exception ex)
1946 { 2034 {
1947 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); 2035 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
1948 } 2036 }
@@ -1950,14 +2038,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1950 Watchdog.UpdateThread(); 2038 Watchdog.UpdateThread();
1951 } 2039 }
1952 2040
1953 if (packetInbox.Count > 0) 2041 if (packetInbox.Count() > 0)
1954 m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count + " packets"); 2042 m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count() + " packets");
1955 packetInbox.Clear(); 2043 packetInbox.Clear();
1956 2044
1957 Watchdog.RemoveThread(); 2045 Watchdog.RemoveThread();
1958 } 2046 }
1959 2047
1960 private void OutgoingPacketHandler() 2048 protected void OutgoingPacketHandler()
1961 { 2049 {
1962 Thread.CurrentThread.Priority = ThreadPriority.Highest; 2050 Thread.CurrentThread.Priority = ThreadPriority.Highest;
1963 2051
@@ -1971,6 +2059,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1971 2059
1972 while (base.IsRunningOutbound) 2060 while (base.IsRunningOutbound)
1973 { 2061 {
2062 Scene.ThreadAlive(2);
2063
2064
1974 try 2065 try
1975 { 2066 {
1976 m_packetSent = false; 2067 m_packetSent = false;
@@ -1982,19 +2073,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1982 m_sendPing = false; 2073 m_sendPing = false;
1983 2074
1984 // Update elapsed time 2075 // Update elapsed time
1985 int thisTick = Environment.TickCount & Int32.MaxValue; 2076 double thisTick = Util.GetTimeStampMS();
1986 if (m_tickLastOutgoingPacketHandler > thisTick)
1987 m_elapsedMSOutgoingPacketHandler += ((Int32.MaxValue - m_tickLastOutgoingPacketHandler) + thisTick);
1988 else
1989 m_elapsedMSOutgoingPacketHandler += (thisTick - m_tickLastOutgoingPacketHandler);
1990 2077
2078 // update some 1ms resolution chained timers
2079 m_elapsedMSOutgoingPacketHandler += thisTick - m_tickLastOutgoingPacketHandler;
1991 m_tickLastOutgoingPacketHandler = thisTick; 2080 m_tickLastOutgoingPacketHandler = thisTick;
1992 2081
1993 // Check for pending outgoing resends every 100ms 2082 // Check for pending outgoing resends every 100ms
1994 if (m_elapsedMSOutgoingPacketHandler >= 100) 2083 if (m_elapsedMSOutgoingPacketHandler >= 100.0)
1995 { 2084 {
1996 m_resendUnacked = true; 2085 m_resendUnacked = true;
1997 m_elapsedMSOutgoingPacketHandler = 0; 2086 m_elapsedMSOutgoingPacketHandler = 0.0;
1998 m_elapsed100MSOutgoingPacketHandler += 1; 2087 m_elapsed100MSOutgoingPacketHandler += 1;
1999 } 2088 }
2000 2089
@@ -2012,15 +2101,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2012 m_sendPing = true; 2101 m_sendPing = true;
2013 m_elapsed500MSOutgoingPacketHandler = 0; 2102 m_elapsed500MSOutgoingPacketHandler = 0;
2014 } 2103 }
2015
2016 #endregion Update Timers 2104 #endregion Update Timers
2017 2105
2018 // Use this for emergency monitoring -- bug hunting
2019 //if (m_scene.EmergencyMonitoring)
2020 // clientPacketHandler = MonitoredClientOutgoingPacketHandler;
2021 //else
2022 // clientPacketHandler = ClientOutgoingPacketHandler;
2023
2024 // Handle outgoing packets, resends, acknowledgements, and pings for each 2106 // Handle outgoing packets, resends, acknowledgements, and pings for each
2025 // client. m_packetSent will be set to true if a packet is sent 2107 // client. m_packetSent will be set to true if a packet is sent
2026 Scene.ForEachClient(clientPacketHandler); 2108 Scene.ForEachClient(clientPacketHandler);
@@ -2029,13 +2111,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2029 2111
2030 // If nothing was sent, sleep for the minimum amount of time before a 2112 // If nothing was sent, sleep for the minimum amount of time before a
2031 // token bucket could get more tokens 2113 // token bucket could get more tokens
2032 //if (!m_packetSent) 2114
2033 // Thread.Sleep((int)TickCountResolution); 2115 if(Scene.GetNumberOfClients() == 0)
2034 // 2116 {
2035 // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with 2117 Thread.Sleep(100);
2036 // modern mono it reduces CPU base load since there is no more continuous polling. 2118 }
2037 if (!m_packetSent) 2119 else if (!m_packetSent)
2038 m_dataPresentEvent.WaitOne(100); 2120// Thread.Sleep((int)TickCountResolution); outch this is bad on linux
2121 Thread.Sleep(15); // match the 16ms of windows7, dont ask 16 or win may decide to do 32ms.
2039 2122
2040 Watchdog.UpdateThread(); 2123 Watchdog.UpdateThread();
2041 } 2124 }
@@ -2061,7 +2144,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2061 2144
2062 if (udpClient.IsConnected) 2145 if (udpClient.IsConnected)
2063 { 2146 {
2064 if (udpClient.ProcessUnackedSends && m_resendUnacked) 2147 if (m_resendUnacked)
2065 HandleUnacked(llClient); 2148 HandleUnacked(llClient);
2066 2149
2067 if (m_sendAcks) 2150 if (m_sendAcks)
@@ -2086,160 +2169,61 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2086 #region Emergency Monitoring 2169 #region Emergency Monitoring
2087 // Alternative packet handler fuull of instrumentation 2170 // Alternative packet handler fuull of instrumentation
2088 // Handy for hunting bugs 2171 // Handy for hunting bugs
2089 private Stopwatch watch1 = new Stopwatch(); 2172 protected Stopwatch watch1 = new Stopwatch();
2090 private Stopwatch watch2 = new Stopwatch(); 2173 protected Stopwatch watch2 = new Stopwatch();
2091 2174
2092 private float avgProcessingTicks = 0; 2175 protected float avgProcessingTicks = 0;
2093 private float avgResendUnackedTicks = 0; 2176 protected float avgResendUnackedTicks = 0;
2094 private float avgSendAcksTicks = 0; 2177 protected float avgSendAcksTicks = 0;
2095 private float avgSendPingTicks = 0; 2178 protected float avgSendPingTicks = 0;
2096 private float avgDequeueTicks = 0; 2179 protected float avgDequeueTicks = 0;
2097 private long nticks = 0; 2180 protected long nticks = 0;
2098 private long nticksUnack = 0; 2181 protected long nticksUnack = 0;
2099 private long nticksAck = 0; 2182 protected long nticksAck = 0;
2100 private long nticksPing = 0; 2183 protected long nticksPing = 0;
2101 private int npacksSent = 0; 2184 protected int npacksSent = 0;
2102 private int npackNotSent = 0; 2185 protected int npackNotSent = 0;
2103 2186
2104 /// <summary> 2187 /// <summary>
2105 /// Number of inbound packets processed since startup. 2188 /// Number of inbound packets processed since startup.
2106 /// </summary> 2189 /// </summary>
2107 public long IncomingPacketsProcessed { get; private set; } 2190 public long IncomingPacketsProcessed { get; protected set; }
2108
2109 private void MonitoredClientOutgoingPacketHandler(IClientAPI client)
2110 {
2111 nticks++;
2112 watch1.Start();
2113 m_currentOutgoingClient = client;
2114
2115 try
2116 {
2117 if (client is LLClientView)
2118 {
2119 LLClientView llClient = (LLClientView)client;
2120 LLUDPClient udpClient = llClient.UDPClient;
2121 2191
2122 if (udpClient.IsConnected) 2192 #endregion
2123 {
2124 if (m_resendUnacked)
2125 {
2126 nticksUnack++;
2127 watch2.Start();
2128
2129 HandleUnacked(llClient);
2130
2131 watch2.Stop();
2132 avgResendUnackedTicks = (nticksUnack - 1)/(float)nticksUnack * avgResendUnackedTicks + (watch2.ElapsedTicks / (float)nticksUnack);
2133 watch2.Reset();
2134 }
2135
2136 if (m_sendAcks)
2137 {
2138 nticksAck++;
2139 watch2.Start();
2140
2141 SendAcks(udpClient);
2142
2143 watch2.Stop();
2144 avgSendAcksTicks = (nticksAck - 1) / (float)nticksAck * avgSendAcksTicks + (watch2.ElapsedTicks / (float)nticksAck);
2145 watch2.Reset();
2146 }
2147
2148 if (m_sendPing)
2149 {
2150 nticksPing++;
2151 watch2.Start();
2152
2153 SendPing(udpClient);
2154 2193
2155 watch2.Stop(); 2194 protected void ProcessInPacket(IncomingPacket incomingPacket)
2156 avgSendPingTicks = (nticksPing - 1) / (float)nticksPing * avgSendPingTicks + (watch2.ElapsedTicks / (float)nticksPing); 2195 {
2157 watch2.Reset(); 2196 Packet packet = incomingPacket.Packet;
2158 } 2197 LLClientView client = incomingPacket.Client;
2159 2198
2160 watch2.Start(); 2199 if(!client.IsActive)
2161 // Dequeue any outgoing packets that are within the throttle limits 2200 return;
2162 if (udpClient.DequeueOutgoing())
2163 {
2164 m_packetSent = true;
2165 npacksSent++;
2166 }
2167 else
2168 {
2169 npackNotSent++;
2170 }
2171 2201
2172 watch2.Stop(); 2202 m_currentIncomingClient = client;
2173 avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks);
2174 watch2.Reset();
2175 2203
2176 } 2204 try
2177 else
2178 {
2179 m_log.WarnFormat("[LLUDPSERVER]: Client is not connected");
2180 }
2181 }
2182 }
2183 catch (Exception ex)
2184 { 2205 {
2185 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name + 2206 // Process this packet
2186 " threw an exception: " + ex.Message, ex); 2207 client.ProcessInPacket(packet);
2187 } 2208 }
2188 watch1.Stop(); 2209 catch(ThreadAbortException)
2189 avgProcessingTicks = (nticks - 1) / (float)nticks * avgProcessingTicks + (watch1.ElapsedTicks / (float)nticks);
2190 watch1.Reset();
2191
2192 // reuse this -- it's every ~100ms
2193 if (Scene.EmergencyMonitoring && nticks % 100 == 0)
2194 { 2210 {
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})", 2211 // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down
2196 avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent); 2212 m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server");
2197 npackNotSent = npacksSent = 0; 2213 Stop();
2198 } 2214 }
2199 2215 catch(Exception e)
2200 }
2201
2202 #endregion
2203
2204 private void ProcessInPacket(IncomingPacket incomingPacket)
2205 {
2206 Packet packet = incomingPacket.Packet;
2207 LLClientView client = incomingPacket.Client;
2208
2209 if (client.IsActive)
2210 { 2216 {
2211 m_currentIncomingClient = client; 2217 // Don't let a failure in an individual client thread crash the whole sim.
2212 2218 m_log.Error(
2213 try 2219 string.Format(
2214 { 2220 "[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw ",
2215 // Process this packet 2221 client.Name,packet.Type),
2216 client.ProcessInPacket(packet); 2222 e);
2217 }
2218 catch (ThreadAbortException)
2219 {
2220 // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down
2221 m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server");
2222 Stop();
2223 }
2224 catch (Exception e)
2225 {
2226 // Don't let a failure in an individual client thread crash the whole sim.
2227 m_log.Error(
2228 string.Format(
2229 "[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw ",
2230 client.Name, packet.Type),
2231 e);
2232 }
2233 finally
2234 {
2235 m_currentIncomingClient = null;
2236 }
2237 } 2223 }
2238 else 2224 finally
2239 { 2225 {
2240 m_log.DebugFormat( 2226 m_currentIncomingClient = null;
2241 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
2242 packet.Type, client.Name, Scene.RegionInfo.RegionName);
2243 } 2227 }
2244 2228
2245 IncomingPacketsProcessed++; 2229 IncomingPacketsProcessed++;