aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
authorUbitUmarov2019-12-18 23:26:13 +0000
committerUbitUmarov2019-12-18 23:26:13 +0000
commit066a6fbaa1ff1a07d181db389a24235fd55e63c9 (patch)
tree1170f2a63c94be4ab9e12ea571e1c9355fa9f890 /OpenSim/Region/ClientStack
parentmissing files (diff)
downloadopensim-SC-066a6fbaa1ff1a07d181db389a24235fd55e63c9.zip
opensim-SC-066a6fbaa1ff1a07d181db389a24235fd55e63c9.tar.gz
opensim-SC-066a6fbaa1ff1a07d181db389a24235fd55e63c9.tar.bz2
opensim-SC-066a6fbaa1ff1a07d181db389a24235fd55e63c9.tar.xz
changes on lludp acks and resends
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs2
-rwxr-xr-xOpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs28
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs175
-rwxr-xr-xOpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs29
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs123
5 files changed, 186 insertions, 171 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 316d39d..35e18a0 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -411,7 +411,7 @@ namespace OpenSim.Region.ClientStack.Linden
411 { 411 {
412 try 412 try
413 { 413 {
414// m_log.Debug("[CAPS]: ScriptTaskInventory Request in region: " + m_regionName); 414 //m_log.Debug("[CAPS]: ScriptTaskInventory Request in region: " + m_regionName);
415 //m_log.DebugFormat("[CAPS]: request: {0}, path: {1}, param: {2}", request, path, param); 415 //m_log.DebugFormat("[CAPS]: request: {0}, path: {1}, param: {2}", request, path, param);
416 416
417 Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request)); 417 Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 645d00b..d0902ff 100755
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -4482,7 +4482,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4482 Utils.FloatToBytesSafepos(hover, data, pos); pos += 4; 4482 Utils.FloatToBytesSafepos(hover, data, pos); pos += 4;
4483 4483
4484 buf.DataLength = pos; 4484 buf.DataLength = pos;
4485 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, false, true); 4485 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority, null, true);
4486 } 4486 }
4487 4487
4488 static private readonly byte[] AvatarAnimationHeader = new byte[] { 4488 static private readonly byte[] AvatarAnimationHeader = new byte[] {
@@ -4638,7 +4638,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4638 CreateImprovedTerseBlock(ent, buf.Data, ref pos, false); 4638 CreateImprovedTerseBlock(ent, buf.Data, ref pos, false);
4639 4639
4640 buf.DataLength = pos; 4640 buf.DataLength = pos;
4641 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true); 4641 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, true);
4642 } 4642 }
4643 4643
4644 //UUID m_courseLocationPrey = UUID.Zero; 4644 //UUID m_courseLocationPrey = UUID.Zero;
@@ -5197,7 +5197,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5197 5197
5198 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, 5198 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
5199 //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); 5199 //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
5200 null, false, false); 5200 null, false);
5201 5201
5202 buf = newbuf; 5202 buf = newbuf;
5203 zc.Data = buf.Data; 5203 zc.Data = buf.Data;
@@ -5221,7 +5221,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5221 buf.DataLength = zc.Finish(); 5221 buf.DataLength = zc.Finish();
5222 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, 5222 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
5223 //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); 5223 //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
5224 null, false, false); 5224 null, false);
5225 } 5225 }
5226 } 5226 }
5227 5227
@@ -5359,7 +5359,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5359 5359
5360 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, 5360 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
5361 //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); 5361 //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
5362 null, false, false); 5362 null, false);
5363 5363
5364 buf = newbuf; 5364 buf = newbuf;
5365 zc.Data = buf.Data; 5365 zc.Data = buf.Data;
@@ -5383,7 +5383,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5383 buf.DataLength = zc.Finish(); 5383 buf.DataLength = zc.Finish();
5384 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, 5384 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
5385 //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); 5385 //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
5386 null, false, false); 5386 null, false);
5387 } 5387 }
5388 } 5388 }
5389 5389
@@ -5432,7 +5432,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5432 5432
5433 buf.Data[countposition] = (byte)count; 5433 buf.Data[countposition] = (byte)count;
5434 buf.DataLength = pos; 5434 buf.DataLength = pos;
5435 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, false); 5435 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false);
5436 5436
5437 buf = newbuf; 5437 buf = newbuf;
5438 data = buf.Data; 5438 data = buf.Data;
@@ -5446,7 +5446,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5446 { 5446 {
5447 buf.Data[countposition] = (byte)count; 5447 buf.Data[countposition] = (byte)count;
5448 buf.DataLength = pos; 5448 buf.DataLength = pos;
5449 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, false); 5449 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false);
5450 } 5450 }
5451 } 5451 }
5452 5452
@@ -5493,8 +5493,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5493 buf.DataLength = lastpos; 5493 buf.DataLength = lastpos;
5494 // zero encode is not as spec 5494 // zero encode is not as spec
5495 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, 5495 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
5496 //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true); 5496 delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, true);
5497 null, false, true); 5497 //null, false, true);
5498 5498
5499 tau = new List<EntityUpdate>(30); 5499 tau = new List<EntityUpdate>(30);
5500 tau.Add(eu); 5500 tau.Add(eu);
@@ -5509,8 +5509,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5509 buf.Data[17] = (byte)count; 5509 buf.Data[17] = (byte)count;
5510 buf.DataLength = pos; 5510 buf.DataLength = pos;
5511 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, 5511 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
5512 //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, true); 5512 //delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, true);
5513 null, false, true); 5513 null, true);
5514 } 5514 }
5515 } 5515 }
5516 5516
@@ -14541,7 +14541,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
14541 LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length); 14541 LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length);
14542 #endregion BinaryStats 14542 #endregion BinaryStats
14543 14543
14544 OutPacket(packet, throttlePacketType, true); 14544 OutPacket(packet, throttlePacketType, true, null);
14545 } 14545 }
14546 14546
14547 /// <summary> 14547 /// <summary>
@@ -15174,7 +15174,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
15174 int pos = 18; 15174 int pos = 18;
15175 CreateImprovedTerseBlock(p, buf.Data, ref pos, false); 15175 CreateImprovedTerseBlock(p, buf.Data, ref pos, false);
15176 buf.DataLength = pos; 15176 buf.DataLength = pos;
15177 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, true); 15177 m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, true);
15178 } 15178 }
15179 } 15179 }
15180 15180
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index 69e53f6..af62d9c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -115,7 +115,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
115 /// <summary>Circuit code that this client is connected on</summary> 115 /// <summary>Circuit code that this client is connected on</summary>
116 public readonly uint CircuitCode; 116 public readonly uint CircuitCode;
117 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary> 117 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
118 public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(256); 118 public IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(1024);
119 119
120 /// <summary>Packets we have sent that need to be ACKed by the client</summary> 120 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
121 public UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); 121 public UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
@@ -123,6 +123,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
123 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> 123 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
124 public DoubleLocklessQueue<uint> PendingAcks = new DoubleLocklessQueue<uint>(); 124 public DoubleLocklessQueue<uint> PendingAcks = new DoubleLocklessQueue<uint>();
125 125
126 public int AckStalls;
127
126 /// <summary>Current packet sequence number</summary> 128 /// <summary>Current packet sequence number</summary>
127 public int CurrentSequence; 129 public int CurrentSequence;
128 /// <summary>Current ping sequence number</summary> 130 /// <summary>Current ping sequence number</summary>
@@ -185,7 +187,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
185 private byte[] m_packedThrottles; 187 private byte[] m_packedThrottles;
186 188
187 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 189 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
188 private int m_maxRTO = 10000; 190 private int m_maxRTO = 3000;
191 private int m_minRTO = 250;
189 public bool m_deliverPackets = true; 192 public bool m_deliverPackets = true;
190 193
191 private float m_burstTime; 194 private float m_burstTime;
@@ -538,46 +541,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
538 /// true if the packet has been queued, 541 /// true if the packet has been queued,
539 /// false if the packet has not been queued and should be sent immediately. 542 /// false if the packet has not been queued and should be sent immediately.
540 /// </returns> 543 /// </returns>
541 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue) 544 public bool EnqueueOutgoing(OutgoingPacket packet)
542 { 545 {
543 return EnqueueOutgoing(packet, forceQueue, false); 546 return EnqueueOutgoing(packet, false);
544 } 547 }
545 548
546 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue, bool highPriority) 549 public bool EnqueueOutgoing(OutgoingPacket packet, bool highPriority)
547 { 550 {
548 int category = (int)packet.Category; 551 int category = (int)packet.Category;
549 552
550 if (category >= 0 && category < m_packetOutboxes.Length) 553 if (category >= 0 && category < m_packetOutboxes.Length)
551 { 554 {
552 DoubleLocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 555 DoubleLocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
553 556 queue.Enqueue(packet, highPriority);
554 if (forceQueue || m_deliverPackets == false) 557 return true;
555 {
556 queue.Enqueue(packet, highPriority);
557 return true;
558 }
559
560 // need to enqueue if queue is not empty
561 if (queue.Count > 0 || m_nextPackets[category] != null)
562 {
563 queue.Enqueue(packet, highPriority);
564 return true;
565 }
566
567 // check bandwidth
568 TokenBucket bucket = m_throttleCategories[category];
569 if (bucket.CheckTokens(packet.Buffer.DataLength))
570 {
571 // enough tokens so it can be sent imediatly by caller
572 bucket.RemoveTokens(packet.Buffer.DataLength);
573 return false;
574 }
575 else
576 {
577 // Force queue specified or not enough tokens in the bucket, queue this packet
578 queue.Enqueue(packet, highPriority);
579 return true;
580 }
581 } 558 }
582 else 559 else
583 { 560 {
@@ -608,33 +585,84 @@ namespace OpenSim.Region.ClientStack.LindenUDP
608 585
609 OutgoingPacket packet = null; 586 OutgoingPacket packet = null;
610 DoubleLocklessQueue<OutgoingPacket> queue; 587 DoubleLocklessQueue<OutgoingPacket> queue;
611 TokenBucket bucket;
612 bool packetSent = false; 588 bool packetSent = false;
613 ThrottleOutPacketTypeFlags emptyCategories = 0; 589 ThrottleOutPacketTypeFlags emptyCategories = 0;
614 590
615 //string queueDebugOutput = String.Empty; // Serious debug business 591 //string queueDebugOutput = String.Empty; // Serious debug business
592 // do resends
616 593
617 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 594 packet = m_nextPackets[0];
595 if (packet != null)
596 {
597 if (packet.Buffer != null)
598 {
599 if (m_throttleCategories[0].RemoveTokens(packet.Buffer.DataLength))
600 {
601 // Send the packet
602 m_udpServer.SendPacketFinal(packet);
603 packetSent = true;
604 m_nextPackets[0] = null;
605 }
606 }
607 else
608 m_nextPackets[0] = null;
609 }
610 else
611 {
612 queue = m_packetOutboxes[0];
613 if (queue != null)
614 {
615 if(queue.Dequeue(out packet))
616 {
617 // A packet was pulled off the queue. See if we have
618 // enough tokens in the bucket to send it out
619 if (packet.Buffer != null)
620 {
621 if (m_throttleCategories[0].RemoveTokens(packet.Buffer.DataLength))
622 {
623 // Send the packet
624 m_udpServer.SendPacketFinal(packet);
625 packetSent = true;
626 }
627 else
628 {
629 // Save the dequeued packet for the next iteration
630 m_nextPackets[0] = packet;
631 }
632 }
633 }
634 }
635 else
636 {
637 m_packetOutboxes[0] = new DoubleLocklessQueue<OutgoingPacket>();
638 }
639 }
640
641 if(NeedAcks.Count() > 50)
642 {
643 Interlocked.Increment(ref AckStalls);
644 return true;
645 }
646
647 for (int i = 1; i < THROTTLE_CATEGORY_COUNT; i++)
618 { 648 {
619 bucket = m_throttleCategories[i];
620 //queueDebugOutput += m_packetOutboxes[i].Count + " "; // Serious debug business 649 //queueDebugOutput += m_packetOutboxes[i].Count + " "; // Serious debug business
621 650
622 if (m_nextPackets[i] != null) 651 packet = m_nextPackets[i];
652 if (packet != null)
623 { 653 {
624 // This bucket was empty the last time we tried to send a packet, 654 if(packet.Buffer == null)
625 // leaving a dequeued packet still waiting to be sent out. Try to
626 // send it again
627 OutgoingPacket nextPacket = m_nextPackets[i];
628 if(nextPacket.Buffer == null)
629 { 655 {
630 if (m_packetOutboxes[i].Count < 5) 656 if (m_packetOutboxes[i].Count < 5)
631 emptyCategories |= CategoryToFlag(i); 657 emptyCategories |= CategoryToFlag(i);
658 m_nextPackets[i] = null;
632 continue; 659 continue;
633 } 660 }
634 if (bucket.RemoveTokens(nextPacket.Buffer.DataLength)) 661
662 if (m_throttleCategories[i].RemoveTokens(packet.Buffer.DataLength))
635 { 663 {
636 // Send the packet 664 // Send the packet
637 m_udpServer.SendPacketFinal(nextPacket); 665 m_udpServer.SendPacketFinal(packet);
638 m_nextPackets[i] = null; 666 m_nextPackets[i] = null;
639 packetSent = true; 667 packetSent = true;
640 668
@@ -647,55 +675,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP
647 // No dequeued packet waiting to be sent, try to pull one off 675 // No dequeued packet waiting to be sent, try to pull one off
648 // this queue 676 // this queue
649 queue = m_packetOutboxes[i]; 677 queue = m_packetOutboxes[i];
650 if (queue != null) 678 if(queue.Dequeue(out packet))
651 { 679 {
652 bool success = false; 680 if (packet.Buffer == null)
653 try
654 {
655 success = queue.Dequeue(out packet);
656 }
657 catch
658 { 681 {
659 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>(); 682 // packet canceled elsewhere (by a ack for example)
683 if (queue.Count < 5)
684 emptyCategories |= CategoryToFlag(i);
685 continue;
660 } 686 }
661 if (success) 687
688 if (m_throttleCategories[i].RemoveTokens(packet.Buffer.DataLength))
662 { 689 {
663 // A packet was pulled off the queue. See if we have 690 // Send the packet
664 // enough tokens in the bucket to send it out 691 m_udpServer.SendPacketFinal(packet);
665 if(packet.Buffer == null) 692 packetSent = true;
666 { 693 if (queue.Count < 5)
667 // packet canceled elsewhere (by a ack for example) 694 emptyCategories |= CategoryToFlag(i);
668 if (queue.Count < 5)
669 emptyCategories |= CategoryToFlag(i);
670 }
671 else
672 {
673 if (bucket.RemoveTokens(packet.Buffer.DataLength))
674 {
675 // Send the packet
676 m_udpServer.SendPacketFinal(packet);
677 packetSent = true;
678
679 if (queue.Count < 5)
680 emptyCategories |= CategoryToFlag(i);
681 }
682 else
683 {
684 // Save the dequeued packet for the next iteration
685 m_nextPackets[i] = packet;
686 }
687 }
688 } 695 }
689 else 696 else
690 { 697 {
691 // No packets in this queue. Fire the queue empty callback 698 // Save the dequeued packet for the next iteration
692 // if it has not been called recently 699 m_nextPackets[i] = packet;
693 emptyCategories |= CategoryToFlag(i);
694 } 700 }
695 } 701 }
696 else 702 else
697 { 703 {
698 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>(); 704 // No packets in this queue. Fire the queue empty callback
705 // if it has not been called recently
699 emptyCategories |= CategoryToFlag(i); 706 emptyCategories |= CategoryToFlag(i);
700 } 707 }
701 } 708 }
@@ -718,8 +725,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
718 p *= 5; 725 p *= 5;
719 if( p> m_maxRTO) 726 if( p> m_maxRTO)
720 p = m_maxRTO; 727 p = m_maxRTO;
721 else if(p < m_defaultRTO) 728 else if(p < m_minRTO)
722 p = m_defaultRTO; 729 p = m_minRTO;
723 730
724 m_RTO = p; 731 m_RTO = p;
725 } 732 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 2863b8d..6994efb 100755
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -880,8 +880,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
880 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will 880 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
881 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object 881 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object
882 // packet so that it isn't sent before a queued update packet. 882 // packet so that it isn't sent before a queued update packet.
883 bool requestQueue = type == PacketType.KillObject; 883 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, highPriority))
884 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority))
885 { 884 {
886 SendPacketFinal(outgoingPacket); 885 SendPacketFinal(outgoingPacket);
887 return true; 886 return true;
@@ -952,7 +951,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
952 } 951 }
953 952
954 public void SendUDPPacket( 953 public void SendUDPPacket(
955 LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool forcequeue, bool zerocode) 954 LLUDPClient udpClient, UDPPacketBuffer buffer, ThrottleOutPacketType category, UnackedPacketMethod method, bool zerocode)
956 { 955 {
957 bool highPriority = false; 956 bool highPriority = false;
958 957
@@ -971,7 +970,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
971 if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0) 970 if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0)
972 outgoingPacket.UnackedMethod = ((method == null) ? delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); 971 outgoingPacket.UnackedMethod = ((method == null) ? delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
973 972
974 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forcequeue, highPriority)) 973 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, highPriority))
975 SendPacketFinal(outgoingPacket); 974 SendPacketFinal(outgoingPacket);
976 } 975 }
977 976
@@ -991,7 +990,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
991 if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0) 990 if ((outgoingPacket.Buffer.Data[0] & Helpers.MSG_RELIABLE) != 0)
992 outgoingPacket.UnackedMethod = delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); }; 991 outgoingPacket.UnackedMethod = delegate (OutgoingPacket oPacket) { ResendUnacked(oPacket); };
993 992
994 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false, highPriority)) 993 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, highPriority))
995 SendPacketFinal(outgoingPacket); 994 SendPacketFinal(outgoingPacket);
996 } 995 }
997 996
@@ -1056,11 +1055,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1056 1055
1057 data[7] = udpClient.CurrentPingSequence++; 1056 data[7] = udpClient.CurrentPingSequence++;
1058 // older seq number of our un ack packets, so viewers could clean deduplication lists TODO 1057 // older seq number of our un ack packets, so viewers could clean deduplication lists TODO
1059 //Utils.UIntToBytes(0, data, 8); 1058 Utils.UIntToBytes(udpClient.NeedAcks.Oldest(), data, 8);
1060 data[8] = 0;
1061 data[9] = 0;
1062 data[10] = 0;
1063 data[11] = 0;
1064 1059
1065 buf.DataLength = 12; 1060 buf.DataLength = 12;
1066 SendUDPPacket(udpClient, buf, ThrottleOutPacketType.Unknown); 1061 SendUDPPacket(udpClient, buf, ThrottleOutPacketType.Unknown);
@@ -1140,7 +1135,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1140 1135
1141 // Bump up the resend count on this packet 1136 // Bump up the resend count on this packet
1142 Interlocked.Increment(ref outgoingPacket.ResendCount); 1137 Interlocked.Increment(ref outgoingPacket.ResendCount);
1143
1144 // Requeue or resend the packet 1138 // Requeue or resend the packet
1145 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false)) 1139 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, false))
1146 SendPacketFinal(outgoingPacket); 1140 SendPacketFinal(outgoingPacket);
@@ -1162,7 +1156,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1162 return; 1156 return;
1163 LLUDPClient udpClient = outgoingPacket.Client; 1157 LLUDPClient udpClient = outgoingPacket.Client;
1164 if (!udpClient.IsConnected) 1158 if (!udpClient.IsConnected)
1159 {
1160 FreeUDPBuffer(buffer);
1165 return; 1161 return;
1162 }
1166 1163
1167 byte flags = buffer.Data[0]; 1164 byte flags = buffer.Data[0];
1168 bool isResend = (flags & Helpers.MSG_RESENT) != 0; 1165 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
@@ -1172,7 +1169,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1172 int dataLength = buffer.DataLength; 1169 int dataLength = buffer.DataLength;
1173 1170
1174 // only append acks on plain reliable messages 1171 // only append acks on plain reliable messages
1175 if (flags == Helpers.MSG_RELIABLE) 1172 if (flags == Helpers.MSG_RELIABLE && outgoingPacket.UnackedMethod == null)
1176 { 1173 {
1177 // Keep appending ACKs until there is no room left in the buffer or there are 1174 // Keep appending ACKs until there is no room left in the buffer or there are
1178 // no more ACKs to append 1175 // no more ACKs to append
@@ -1211,10 +1208,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1211 // Stats tracking 1208 // Stats tracking
1212 Interlocked.Increment(ref udpClient.PacketsSent); 1209 Interlocked.Increment(ref udpClient.PacketsSent);
1213 PacketsSentCount++; 1210 PacketsSentCount++;
1211
1214 SyncSend(buffer); 1212 SyncSend(buffer);
1215 1213
1216 // Keep track of when this packet was sent out (right now) 1214 // Keep track of when this packet was sent out (right now)
1217 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; 1215 int enow = Environment.TickCount & Int32.MaxValue;
1216 Interlocked.Exchange(ref outgoingPacket.TickCount, enow);
1218 1217
1219 if (outgoingPacket.UnackedMethod == null) 1218 if (outgoingPacket.UnackedMethod == null)
1220 FreeUDPBuffer(buffer); 1219 FreeUDPBuffer(buffer);
@@ -1935,7 +1934,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1935 { 1934 {
1936 m_resendUnacked = true; 1935 m_resendUnacked = true;
1937 m_elapsedMSOutgoingPacketHandler = 0.0; 1936 m_elapsedMSOutgoingPacketHandler = 0.0;
1938 m_elapsed100MSOutgoingPacketHandler += 1; 1937 ++m_elapsed100MSOutgoingPacketHandler;
1939 } 1938 }
1940 1939
1941 // Check for pending outgoing ACKs every 500ms 1940 // Check for pending outgoing ACKs every 500ms
@@ -1943,7 +1942,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1943 { 1942 {
1944 m_sendAcks = true; 1943 m_sendAcks = true;
1945 m_elapsed100MSOutgoingPacketHandler = 0; 1944 m_elapsed100MSOutgoingPacketHandler = 0;
1946 m_elapsed500MSOutgoingPacketHandler += 1; 1945 ++m_elapsed500MSOutgoingPacketHandler;
1947 } 1946 }
1948 1947
1949 // Send pings to clients every 5000ms 1948 // Send pings to clients every 5000ms
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
index 32a6c40..af5b2ae 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/UnackedPacketCollection.cs
@@ -66,21 +66,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
66 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 66 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67 67
68 /// <summary>Holds the actual unacked packet data, sorted by sequence number</summary> 68 /// <summary>Holds the actual unacked packet data, sorted by sequence number</summary>
69 private Dictionary<uint, OutgoingPacket> m_packets = new Dictionary<uint, OutgoingPacket>(); 69 private SortedDictionary<uint, OutgoingPacket> m_packets = new SortedDictionary<uint, OutgoingPacket>();
70 /// <summary>Holds packets that need to be added to the unacknowledged list</summary> 70 /// <summary>Holds packets that need to be added to the unacknowledged list</summary>
71 private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>(); 71 private LocklessQueue<OutgoingPacket> m_pendingAdds = new LocklessQueue<OutgoingPacket>();
72 /// <summary>Holds information about pending acknowledgements</summary> 72 /// <summary>Holds information about pending acknowledgements</summary>
73 private LocklessQueue<PendingAck> m_pendingAcknowledgements = new LocklessQueue<PendingAck>(); 73 private LocklessQueue<PendingAck> m_pendingAcknowledgements = new LocklessQueue<PendingAck>();
74 /// <summary>Holds information about pending removals</summary> 74 /// <summary>Holds information about pending removals</summary>
75 private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>(); 75 private LocklessQueue<uint> m_pendingRemoves = new LocklessQueue<uint>();
76 76 private uint m_older;
77
78 public void Clear() 77 public void Clear()
79 { 78 {
80 m_packets.Clear(); 79 m_packets.Clear();
81 m_pendingAdds = null; 80 m_pendingAdds = null;
82 m_pendingAcknowledgements = null; 81 m_pendingAcknowledgements = null;
83 m_pendingRemoves = null; 82 m_pendingRemoves = null;
83 m_older = 0;
84 }
85
86 public int Count()
87 {
88 return m_packets.Count + m_pendingAdds.Count - m_pendingAcknowledgements.Count - m_pendingRemoves.Count;
89 }
90
91 public uint Oldest()
92 {
93 return m_older;
84 } 94 }
85 95
86 /// <summary> 96 /// <summary>
@@ -148,33 +158,47 @@ namespace OpenSim.Region.ClientStack.LindenUDP
148 ProcessQueues(); 158 ProcessQueues();
149 159
150 List<OutgoingPacket> expiredPackets = null; 160 List<OutgoingPacket> expiredPackets = null;
151 161 bool doolder = true;
152 if (m_packets.Count > 0) 162 if (m_packets.Count > 0)
153 { 163 {
154 int now = Environment.TickCount & Int32.MaxValue; 164 int now = Environment.TickCount & Int32.MaxValue;
155 165
156 foreach (OutgoingPacket packet in m_packets.Values) 166 foreach (OutgoingPacket packet in m_packets.Values)
157 { 167 {
168 if(packet.Buffer == null)
169 {
170 Remove(packet.SequenceNumber);
171 continue;
172 }
173
174 if(doolder)
175 {
176 m_older = packet.SequenceNumber;
177 doolder = false;
178 }
179
158 // TickCount of zero means a packet is in the resend queue 180 // TickCount of zero means a packet is in the resend queue
159 // but hasn't actually been sent over the wire yet 181 // but hasn't actually been sent over the wire yet
160 if (packet.TickCount == 0) 182 int ptime = Interlocked.Exchange(ref packet.TickCount, 0);
183 if (ptime == 0)
161 continue; 184 continue;
162 185
163 if (now - packet.TickCount >= timeoutMS) 186 if(now - ptime < timeoutMS)
164 { 187 {
165 if (expiredPackets == null) 188 int t = Interlocked.Exchange(ref packet.TickCount, ptime);
166 expiredPackets = new List<OutgoingPacket>(); 189 if (t > ptime)
190 Interlocked.Exchange(ref packet.TickCount, t);
191 continue;
192 }
167 193
168 // The TickCount will be set to the current time when the packet 194 if (expiredPackets == null)
169 // is actually sent out again 195 expiredPackets = new List<OutgoingPacket>();
170 packet.TickCount = 0;
171 196
172 // As with other network applications, assume that an expired packet is 197 // As with other network applications, assume that an expired packet is
173 // an indication of some network problem, slow transmission 198 // an indication of some network problem, slow transmission
174 packet.Client.FlowThrottle.ExpirePackets(1); 199 packet.Client.FlowThrottle.ExpirePackets(1);
175 200
176 expiredPackets.Add(packet); 201 expiredPackets.Add(packet);
177 }
178 } 202 }
179 } 203 }
180 204
@@ -186,65 +210,50 @@ namespace OpenSim.Region.ClientStack.LindenUDP
186 210
187 private void ProcessQueues() 211 private void ProcessQueues()
188 { 212 {
213 while (m_pendingRemoves.TryDequeue(out uint pendingRemove))
214 {
215 if (m_packets.TryGetValue(pendingRemove, out OutgoingPacket removedPacket))
216 {
217 m_packets.Remove(pendingRemove);
218 if (removedPacket != null)
219 {
220 // Update stats
221 Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
222
223 removedPacket.Client.FreeUDPBuffer(removedPacket.Buffer);
224 removedPacket.Buffer = null;
225 }
226 }
227 }
228
189 // Process all the pending adds 229 // Process all the pending adds
190 OutgoingPacket pendingAdd; 230 while (m_pendingAdds.TryDequeue(out OutgoingPacket pendingAdd))
191 while (m_pendingAdds.TryDequeue(out pendingAdd))
192 { 231 {
193 if (pendingAdd != null) 232 if (pendingAdd != null)
194 m_packets[pendingAdd.SequenceNumber] = pendingAdd; 233 m_packets[pendingAdd.SequenceNumber] = pendingAdd;
195 } 234 }
196 235
197 // Process all the pending removes, including updating statistics and round-trip times 236 // Process all the pending removes, including updating statistics and round-trip times
198 PendingAck pendingAcknowledgement; 237 while (m_pendingAcknowledgements.TryDequeue(out PendingAck pendingAcknowledgement))
199 while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
200 { 238 {
201 //m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Processing ack {0}", pendingAcknowledgement.SequenceNumber); 239 //m_log.DebugFormat("[UNACKED PACKET COLLECTION]: Processing ack {0}", pendingAcknowledgement.SequenceNumber);
202 OutgoingPacket ackedPacket; 240 if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out OutgoingPacket ackedPacket))
203 if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
204 { 241 {
242 m_packets.Remove(pendingAcknowledgement.SequenceNumber);
205 if (ackedPacket != null) 243 if (ackedPacket != null)
206 { 244 {
207 m_packets.Remove(pendingAcknowledgement.SequenceNumber);
208
209 // Update stats 245 // Update stats
210 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); 246 if(ackedPacket.Buffer != null)
211 247 {
212 ackedPacket.Client.FreeUDPBuffer(ackedPacket.Buffer); 248 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
213 ackedPacket.Buffer = null;
214 249
250 ackedPacket.Client.FreeUDPBuffer(ackedPacket.Buffer);
251 ackedPacket.Buffer = null;
252 }
215 // As with other network applications, assume that an acknowledged packet is an 253 // As with other network applications, assume that an acknowledged packet is an
216 // indication that the network can handle a little more load, speed up the transmission 254 // indication that the network can handle a little more load, speed up the transmission
217 ackedPacket.Client.FlowThrottle.AcknowledgePackets(1); 255 ackedPacket.Client.FlowThrottle.AcknowledgePackets(1);
218 } 256 }
219 else
220 {
221 // m_log.WarnFormat("[UNACKED PACKET COLLECTION]: found null packet for sequence number {0} to ack",
222 // pendingAcknowledgement.SequenceNumber);
223 }
224 }
225 else
226 {
227 // m_log.WarnFormat("[UNACKED PACKET COLLECTION]: Could not find packet with sequence number {0} to ack",
228 // pendingAcknowledgement.SequenceNumber);
229 }
230 }
231
232 uint pendingRemove;
233 while(m_pendingRemoves.TryDequeue(out pendingRemove))
234 {
235 OutgoingPacket removedPacket;
236 if (m_packets.TryGetValue(pendingRemove, out removedPacket))
237 {
238 if (removedPacket != null)
239 {
240 m_packets.Remove(pendingRemove);
241
242 // Update stats
243 Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
244
245 removedPacket.Client.FreeUDPBuffer(removedPacket.Buffer);
246 removedPacket.Buffer = null;
247 }
248 } 257 }
249 } 258 }
250 } 259 }