29 using System.Collections.Generic;
31 using System.Threading;
37 namespace OpenSim.
Region.ClientStack.LindenUDP
47 private struct PendingAck
50 public uint SequenceNumber;
53 public int RemoveTime;
56 public bool FromResend;
58 public PendingAck(uint sequenceNumber,
int currentTime,
bool fromResend)
60 SequenceNumber = sequenceNumber;
61 RemoveTime = currentTime;
62 FromResend = fromResend;
69 private Dictionary<uint, OutgoingPacket> m_packets =
new Dictionary<uint, OutgoingPacket>();
71 private LocklessQueue<OutgoingPacket> m_pendingAdds =
new LocklessQueue<OutgoingPacket>();
73 private LocklessQueue<PendingAck> m_pendingAcknowledgements =
new LocklessQueue<PendingAck>();
75 private LocklessQueue<uint> m_pendingRemoves =
new LocklessQueue<uint>();
87 m_pendingAdds.Enqueue(packet);
88 Interlocked.Add(ref packet.Client.UnackedBytes, packet.Buffer.DataLength);
102 public void Acknowledge(uint sequenceNumber,
int currentTime,
bool fromResend)
104 m_pendingAcknowledgements.Enqueue(
new PendingAck(sequenceNumber, currentTime, fromResend));
119 m_pendingRemoves.Enqueue(sequenceNumber);
141 List<OutgoingPacket> expiredPackets = null;
143 if (m_packets.Count > 0)
145 int now = Environment.TickCount & Int32.MaxValue;
156 if (expiredPackets == null)
157 expiredPackets =
new List<OutgoingPacket>();
161 packet.TickCount = 0;
165 packet.Client.FlowThrottle.ExpirePackets(1);
167 expiredPackets.Add(packet);
175 return expiredPackets;
178 private void ProcessQueues()
182 while (m_pendingAdds.TryDequeue(out pendingAdd))
183 if (pendingAdd != null)
184 m_packets[pendingAdd.SequenceNumber] = pendingAdd;
187 PendingAck pendingAcknowledgement;
188 while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
192 if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
194 if (ackedPacket != null)
196 m_packets.Remove(pendingAcknowledgement.SequenceNumber);
200 ackedPacket.Client.FlowThrottle.AcknowledgePackets(1);
203 Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
205 if (!pendingAcknowledgement.FromResend)
208 int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount;
210 ackedPacket.Client.UpdateRoundTrip(rtt);
227 while(m_pendingRemoves.TryDequeue(out pendingRemove))
229 OutgoingPacket removedPacket;
230 if (m_packets.TryGetValue(pendingRemove, out removedPacket))
232 if (removedPacket != null)
234 m_packets.Remove(pendingRemove);
237 Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
void Add(OutgoingPacket packet)
Add an unacked packet to the collection
int TickCount
Environment.TickCount when this packet was last sent over the wire
void Acknowledge(uint sequenceNumber, int currentTime, bool fromResend)
Marks a packet as acknowledged This method is used when an acknowledgement is received from the netwo...
List< OutgoingPacket > GetExpiredPackets(int timeoutMS)
Returns a list of all of the packets with a TickCount older than the specified timeout ...
Special collection that is optimized for tracking unacknowledged packets
void Remove(uint sequenceNumber)
Marks a packet as no longer needing acknowledgement without a received acknowledgement. This method is called when a packet expires and we no longer need an acknowledgement. When some reliable packet types expire, they are handled in a way other than simply resending them. The only effect of removal this way is to update unacked byte count.
Holds a reference to the LLUDPClientthis packet is destined for, along with the serialized packet dat...