diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden')
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 | } |