diff options
| author | Andrey Lihatskiy <alihatskiy@productengine.com> | 2024-05-22 20:51:58 +0300 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-22 20:51:58 +0300 | 
| commit | 6cc7dd09d5e69cf57e6de7fb568a0ad2693f9c9a (patch) | |
| tree | fab23811a5cedc1ebf01479c852ee92ff62b636c /indra/llmessage/llpacketring.cpp | |
| parent | ef8f4819822288e044ea719feb6af7a1f4df4c4e (diff) | |
| parent | 7bb5afc11ee5a6af78302a8d76a9a619e2baaab2 (diff) | |
Merge pull request #1545 from Ansariel/DRTVWR-600-maint-A
Merge main into DRTVWR-600-maint-a
Diffstat (limited to 'indra/llmessage/llpacketring.cpp')
| -rw-r--r-- | indra/llmessage/llpacketring.cpp | 742 | 
1 files changed, 371 insertions, 371 deletions
diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index 8e098bfc8c..8f96554939 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -1,371 +1,371 @@ -/**  - * @file llpacketring.cpp - * @brief implementation of LLPacketRing class for a packet. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llpacketring.h" - -#if LL_WINDOWS -	#include <winsock2.h> -#else -	#include <sys/socket.h> -	#include <netinet/in.h> -#endif - -// linden library includes -#include "llerror.h" -#include "lltimer.h" -#include "llproxy.h" -#include "llrand.h" -#include "message.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. -					LL_WARNS() << "Throwing away packet, overflowing buffer" << LL_ENDL; -					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 -		if (LLProxy::isSOCKSProxyEnabled()) -		{ -			U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; -			packet_size = receive_packet(socket, static_cast<char*>(static_cast<void*>(buffer))); -			 -			if (packet_size > SOCKS_HEADER_SIZE) -			{ -				// *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6) -				memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE); -				proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer)); -				mLastSender.setAddress(header->addr); -				mLastSender.setPort(ntohs(header->port)); - -				packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size -			} -			else -			{ -				packet_size = 0; -			} -		} -		else -		{ -			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 sendPacketImpl(h_socket, send_buffer, buf_size, host ); -	} -	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 = sendPacketImpl(h_socket, packetp->getData(), packet_size, packetp->getHost()); -				 -				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 =  sendPacketImpl(h_socket, send_buffer, buf_size, host ); -				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. -			LL_WARNS() << "Throwing away outbound packet, overflowing buffer" << LL_ENDL; -		} -		else -		{ -			static LLTimer queue_timer; -			if ((mOutBufferLength > 4192) && queue_timer.getElapsedTimeF32() > 1.f) -			{ -				// Add it to the queue -				LL_INFOS() << "Outbound packet queue " << mOutBufferLength << " bytes" << LL_ENDL; -				queue_timer.reset(); -			} -			packetp = new LLPacketBuffer(host, send_buffer, buf_size); - -			mOutBufferLength += packetp->getSize(); -			mSendQueue.push(packetp); -		} -	} - -	return status; -} - -bool LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host) -{ -	 -	if (!LLProxy::isSOCKSProxyEnabled()) -	{ -		return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort()); -	} - -	char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; - -	proxywrap_t *socks_header = static_cast<proxywrap_t*>(static_cast<void*>(&headered_send_buffer)); -	socks_header->rsv   = 0; -	socks_header->addr  = host.getAddress(); -	socks_header->port  = htons(host.getPort()); -	socks_header->atype = ADDRESS_IPV4; -	socks_header->frag  = 0; - -	memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, send_buffer, buf_size); - -	return send_packet(	h_socket, -						headered_send_buffer, -						buf_size + SOCKS_HEADER_SIZE, -						LLProxy::getInstance()->getUDPProxy().getAddress(), -						LLProxy::getInstance()->getUDPProxy().getPort()); -} +/**
 + * @file llpacketring.cpp
 + * @brief implementation of LLPacketRing class for a packet.
 + *
 + * $LicenseInfo:firstyear=2001&license=viewerlgpl$
 + * Second Life Viewer Source Code
 + * Copyright (C) 2010, Linden Research, Inc.
 + *
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation;
 + * version 2.1 of the License only.
 + *
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with this library; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 + *
 + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 + * $/LicenseInfo$
 + */
 +
 +#include "linden_common.h"
 +
 +#include "llpacketring.h"
 +
 +#if LL_WINDOWS
 +    #include <winsock2.h>
 +#else
 +    #include <sys/socket.h>
 +    #include <netinet/in.h>
 +#endif
 +
 +// linden library includes
 +#include "llerror.h"
 +#include "lltimer.h"
 +#include "llproxy.h"
 +#include "llrand.h"
 +#include "message.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.
 +                    LL_WARNS() << "Throwing away packet, overflowing buffer" << LL_ENDL;
 +                    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
 +        if (LLProxy::isSOCKSProxyEnabled())
 +        {
 +            U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
 +            packet_size = receive_packet(socket, static_cast<char*>(static_cast<void*>(buffer)));
 +
 +            if (packet_size > SOCKS_HEADER_SIZE)
 +            {
 +                // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6)
 +                memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE);
 +                proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer));
 +                mLastSender.setAddress(header->addr);
 +                mLastSender.setPort(ntohs(header->port));
 +
 +                packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size
 +            }
 +            else
 +            {
 +                packet_size = 0;
 +            }
 +        }
 +        else
 +        {
 +            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 sendPacketImpl(h_socket, send_buffer, buf_size, host );
 +    }
 +    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 = sendPacketImpl(h_socket, packetp->getData(), packet_size, packetp->getHost());
 +
 +                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 =  sendPacketImpl(h_socket, send_buffer, buf_size, host );
 +                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.
 +            LL_WARNS() << "Throwing away outbound packet, overflowing buffer" << LL_ENDL;
 +        }
 +        else
 +        {
 +            static LLTimer queue_timer;
 +            if ((mOutBufferLength > 4192) && queue_timer.getElapsedTimeF32() > 1.f)
 +            {
 +                // Add it to the queue
 +                LL_INFOS() << "Outbound packet queue " << mOutBufferLength << " bytes" << LL_ENDL;
 +                queue_timer.reset();
 +            }
 +            packetp = new LLPacketBuffer(host, send_buffer, buf_size);
 +
 +            mOutBufferLength += packetp->getSize();
 +            mSendQueue.push(packetp);
 +        }
 +    }
 +
 +    return status;
 +}
 +
 +bool LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host)
 +{
 +
 +    if (!LLProxy::isSOCKSProxyEnabled())
 +    {
 +        return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort());
 +    }
 +
 +    char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
 +
 +    proxywrap_t *socks_header = static_cast<proxywrap_t*>(static_cast<void*>(&headered_send_buffer));
 +    socks_header->rsv   = 0;
 +    socks_header->addr  = host.getAddress();
 +    socks_header->port  = htons(host.getPort());
 +    socks_header->atype = ADDRESS_IPV4;
 +    socks_header->frag  = 0;
 +
 +    memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, send_buffer, buf_size);
 +
 +    return send_packet( h_socket,
 +                        headered_send_buffer,
 +                        buf_size + SOCKS_HEADER_SIZE,
 +                        LLProxy::getInstance()->getUDPProxy().getAddress(),
 +                        LLProxy::getInstance()->getUDPProxy().getPort());
 +}
  | 
