public bool EnqueueOutgoing(OutgoingPacket packet) { int category = (int)packet.Category; if (category >= 0 && category < m_packetOutboxes.Length) { OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; // Not enough tokens in the bucket, queue this packet //check the queue //Dont drop resends this can mess up the buffer pool as well as make the connection situation much worse if (_currentOutboundQueueSize > MAX_TOTAL_QUEUE_SIZE && (packet.Buffer[0] & Helpers.MSG_RESENT) == 0) { //queue already has too much data in it.. //can we drop this packet? byte flags = packet.Buffer[0]; bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; if (!isReliable && packet.Type != PacketType.PacketAck && packet.Type != PacketType.CompletePingCheck) { //packet is unreliable and will be dropped this.TestReportPacketDrop(packet); packet.DecRef(m_udpServer.ByteBufferPool); } else { if (_currentOutboundQueueSize < MAX_TOTAL_QUEUE_SIZE * 1.5) { this.TestReportPacketShouldDrop(packet); Interlocked.Add(ref _currentOutboundQueueSize, packet.DataSize); packet.AddRef(); queue.Enqueue(packet); } else { //this connection is in a pretty critical state and probably will never catch up. //drop all packets until we start to catch up. This includes acks which will disconnect //the client eventually anyways this.TestReportCriticalPacketDrop(packet); packet.DecRef(m_udpServer.ByteBufferPool); } } } else { Interlocked.Add(ref _currentOutboundQueueSize, packet.DataSize); packet.AddRef(); queue.Enqueue(packet); } return true; } else { // We don't have a token bucket for this category, so it will not be queued return false; } }
public bool EnqueueOutgoing(OutgoingPacket packet) { int category = (int)packet.Category; if (category >= 0 && category < m_packetOutboxes.Length) { OpenSim.Framework.LocklessQueue <OutgoingPacket> queue = m_packetOutboxes[category]; // Not enough tokens in the bucket, queue this packet //check the queue //Dont drop resends this can mess up the buffer pool as well as make the connection situation much worse if (_currentOutboundQueueSize > MAX_TOTAL_QUEUE_SIZE && (packet.Buffer[0] & Helpers.MSG_RESENT) == 0) { //queue already has too much data in it.. //can we drop this packet? byte flags = packet.Buffer[0]; bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; if (!isReliable && packet.Type != PacketType.PacketAck && packet.Type != PacketType.CompletePingCheck) { //packet is unreliable and will be dropped this.TestReportPacketDrop(packet); packet.DecRef(m_udpServer.ByteBufferPool); } else { if (_currentOutboundQueueSize < MAX_TOTAL_QUEUE_SIZE * 1.5) { this.TestReportPacketShouldDrop(packet); Interlocked.Add(ref _currentOutboundQueueSize, packet.DataSize); packet.AddRef(); queue.Enqueue(packet); } else { //this connection is in a pretty critical state and probably will never catch up. //drop all packets until we start to catch up. This includes acks which will disconnect //the client eventually anyways this.TestReportCriticalPacketDrop(packet); packet.DecRef(m_udpServer.ByteBufferPool); } } } else { Interlocked.Add(ref _currentOutboundQueueSize, packet.DataSize); packet.AddRef(); queue.Enqueue(packet); } return(true); } else { // We don't have a token bucket for this category, so it will not be queued return(false); } }
/// <summary> /// Loops through all of the packet queues for this client and tries to send /// any outgoing packets, obeying the throttling bucket limits /// </summary> /// <remarks>This function is only called from a synchronous loop in the /// UDPServer so we don't need to bother making this thread safe</remarks> /// <returns>True if any packets were sent, otherwise false</returns> public bool DequeueOutgoing() { OutgoingPacket packet; OpenSim.Framework.LocklessQueue <OutgoingPacket> queue; TokenBucket bucket; bool packetSent = false; ThrottleOutPacketTypeFlags emptyCategories = 0; //string queueDebugOutput = String.Empty; // Serious debug business int randStart = _rand.Next(7); for (int j = 0; j < THROTTLE_CATEGORY_COUNT; j++) { int i = (j + randStart) % THROTTLE_CATEGORY_COUNT; bucket = m_throttleCategories[i]; //queueDebugOutput += m_packetOutboxes[i].Count + " "; // Serious debug business if (m_nextPackets[i] != null) { // This bucket was empty the last time we tried to send a packet, // leaving a dequeued packet still waiting to be sent out. Try to // send it again OutgoingPacket nextPacket = m_nextPackets[i]; if (bucket.RemoveTokens(nextPacket.DataSize)) { // Send the packet Interlocked.Add(ref _currentOutboundQueueSize, -nextPacket.DataSize); m_udpServer.SendPacketFinal(nextPacket); nextPacket.DecRef(m_udpServer.ByteBufferPool); m_nextPackets[i] = null; packetSent = true; this.PacketsSent++; } } else { // No dequeued packet waiting to be sent, try to pull one off // this queue queue = m_packetOutboxes[i]; if (queue.Dequeue(out packet)) { // A packet was pulled off the queue. See if we have // enough tokens in the bucket to send it out if (bucket.RemoveTokens(packet.DataSize)) { // Send the packet Interlocked.Add(ref _currentOutboundQueueSize, -packet.DataSize); m_udpServer.SendPacketFinal(packet); packet.DecRef(m_udpServer.ByteBufferPool); packetSent = true; this.PacketsSent++; } else { // Save the dequeued packet for the next iteration m_nextPackets[i] = packet; _emptyBucketHints.Add(i); } // If the queue is empty after this dequeue, fire the queue // empty callback now so it has a chance to fill before we // get back here if (queue.Count == 0) { emptyCategories |= CategoryToFlag(i); } } else { // No packets in this queue. Fire the queue empty callback // if it has not been called recently emptyCategories |= CategoryToFlag(i); } } } if (emptyCategories != 0) { BeginFireQueueEmpty(emptyCategories); } //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business return(packetSent); }
protected override void SendCompleted(OutgoingPacket packet) { packet.DecRef(_bufferPool); }