llpacketring.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:8k
- /**
- * @file llpacketring.cpp
- * @brief implementation of LLPacketRing class for a packet.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2010, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include "llpacketring.h"
- // linden library includes
- #include "llerror.h"
- #include "lltimer.h"
- #include "timing.h"
- #include "llrand.h"
- #include "u64.h"
- ///////////////////////////////////////////////////////////
- LLPacketRing::LLPacketRing () :
- mUseInThrottle(FALSE),
- mUseOutThrottle(FALSE),
- mInThrottle(256000.f),
- mOutThrottle(64000.f),
- mActualBitsIn(0),
- mActualBitsOut(0),
- mMaxBufferLength(64000),
- mInBufferLength(0),
- mOutBufferLength(0),
- mDropPercentage(0.0f),
- mPacketsToDrop(0x0)
- {
- }
- ///////////////////////////////////////////////////////////
- LLPacketRing::~LLPacketRing ()
- {
- cleanup();
- }
-
- ///////////////////////////////////////////////////////////
- void LLPacketRing::cleanup ()
- {
- LLPacketBuffer *packetp;
- while (!mReceiveQueue.empty())
- {
- packetp = mReceiveQueue.front();
- delete packetp;
- mReceiveQueue.pop();
- }
- while (!mSendQueue.empty())
- {
- packetp = mSendQueue.front();
- delete packetp;
- mSendQueue.pop();
- }
- }
- ///////////////////////////////////////////////////////////
- void LLPacketRing::dropPackets (U32 num_to_drop)
- {
- mPacketsToDrop += num_to_drop;
- }
- ///////////////////////////////////////////////////////////
- void LLPacketRing::setDropPercentage (F32 percent_to_drop)
- {
- mDropPercentage = percent_to_drop;
- }
- void LLPacketRing::setUseInThrottle(const BOOL use_throttle)
- {
- mUseInThrottle = use_throttle;
- }
- void LLPacketRing::setUseOutThrottle(const BOOL use_throttle)
- {
- mUseOutThrottle = use_throttle;
- }
- void LLPacketRing::setInBandwidth(const F32 bps)
- {
- mInThrottle.setRate(bps);
- }
- void LLPacketRing::setOutBandwidth(const F32 bps)
- {
- mOutThrottle.setRate(bps);
- }
- ///////////////////////////////////////////////////////////
- S32 LLPacketRing::receiveFromRing (S32 socket, char *datap)
- {
- if (mInThrottle.checkOverflow(0))
- {
- // We don't have enough bandwidth, don't give them a packet.
- return 0;
- }
- LLPacketBuffer *packetp = NULL;
- if (mReceiveQueue.empty())
- {
- // No packets on the queue, don't give them any.
- return 0;
- }
- S32 packet_size = 0;
- packetp = mReceiveQueue.front();
- mReceiveQueue.pop();
- packet_size = packetp->getSize();
- if (packetp->getData() != NULL)
- {
- memcpy(datap, packetp->getData(), packet_size); /*Flawfinder: ignore*/
- }
- // need to set sender IP/port!!
- mLastSender = packetp->getHost();
- mLastReceivingIF = packetp->getReceivingInterface();
- delete packetp;
- this->mInBufferLength -= packet_size;
- // Adjust the throttle
- mInThrottle.throttleOverflow(packet_size * 8.f);
- return packet_size;
- }
- ///////////////////////////////////////////////////////////
- S32 LLPacketRing::receivePacket (S32 socket, char *datap)
- {
- S32 packet_size = 0;
- // If using the throttle, simulate a limited size input buffer.
- if (mUseInThrottle)
- {
- BOOL done = FALSE;
- // push any current net packet (if any) onto delay ring
- while (!done)
- {
- LLPacketBuffer *packetp;
- packetp = new LLPacketBuffer(socket);
- if (packetp->getSize())
- {
- mActualBitsIn += packetp->getSize() * 8;
- // Fake packet loss
- if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
- {
- mPacketsToDrop++;
- }
- if (mPacketsToDrop)
- {
- delete packetp;
- packetp = NULL;
- packet_size = 0;
- mPacketsToDrop--;
- }
- }
- // If we faked packet loss, then we don't have a packet
- // to use for buffer overflow testing
- if (packetp)
- {
- if (mInBufferLength + packetp->getSize() > mMaxBufferLength)
- {
- // Toss it.
- llwarns << "Throwing away packet, overflowing buffer" << llendl;
- delete packetp;
- packetp = NULL;
- }
- else if (packetp->getSize())
- {
- mReceiveQueue.push(packetp);
- mInBufferLength += packetp->getSize();
- }
- else
- {
- delete packetp;
- packetp = NULL;
- done = true;
- }
- }
- else
- {
- // No packetp, keep going? - no packetp == faked packet loss
- }
- }
- // Now, grab data off of the receive queue according to our
- // throttled bandwidth settings.
- packet_size = receiveFromRing(socket, datap);
- }
- else
- {
- // no delay, pull straight from net
- packet_size = receive_packet(socket, datap);
- mLastSender = ::get_sender();
- mLastReceivingIF = ::get_receiving_interface();
- if (packet_size) // did we actually get a packet?
- {
- if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
- {
- mPacketsToDrop++;
- }
- if (mPacketsToDrop)
- {
- packet_size = 0;
- mPacketsToDrop--;
- }
- }
- }
- return packet_size;
- }
- BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host)
- {
- BOOL status = TRUE;
- if (!mUseOutThrottle)
- {
- return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() );
- }
- else
- {
- mActualBitsOut += buf_size * 8;
- LLPacketBuffer *packetp = NULL;
- // See if we've got enough throttle to send a packet.
- while (!mOutThrottle.checkOverflow(0.f))
- {
- // While we have enough bandwidth, send a packet from the queue or the current packet
- S32 packet_size = 0;
- if (!mSendQueue.empty())
- {
- // Send a packet off of the queue
- LLPacketBuffer *packetp = mSendQueue.front();
- mSendQueue.pop();
- mOutBufferLength -= packetp->getSize();
- packet_size = packetp->getSize();
- status = send_packet(h_socket, packetp->getData(), packet_size, packetp->getHost().getAddress(), packetp->getHost().getPort());
-
- delete packetp;
- // Update the throttle
- mOutThrottle.throttleOverflow(packet_size * 8.f);
- }
- else
- {
- // If the queue's empty, we can just send this packet right away.
- status = send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() );
- packet_size = buf_size;
- // Update the throttle
- mOutThrottle.throttleOverflow(packet_size * 8.f);
- // This was the packet we're sending now, there are no other packets
- // that we need to send
- return status;
- }
- }
- // We haven't sent the incoming packet, add it to the queue
- if (mOutBufferLength + buf_size > mMaxBufferLength)
- {
- // Nuke this packet, we overflowed the buffer.
- // Toss it.
- llwarns << "Throwing away outbound packet, overflowing buffer" << llendl;
- }
- else
- {
- static LLTimer queue_timer;
- if ((mOutBufferLength > 4192) && queue_timer.getElapsedTimeF32() > 1.f)
- {
- // Add it to the queue
- llinfos << "Outbound packet queue " << mOutBufferLength << " bytes" << llendl;
- queue_timer.reset();
- }
- packetp = new LLPacketBuffer(host, send_buffer, buf_size);
- mOutBufferLength += packetp->getSize();
- mSendQueue.push(packetp);
- }
- }
- return status;
- }