Ejemplo n.º 1
0
        private int HandleBandwidthLimit(Peer peer, Protocol.BandwidthLimit command)
        {
            peer.IncomingBandwidth = command.IncomingBandwidth;
            peer.OutgoingBandwidth = command.OutgoingBandwidth;

            if (peer.IncomingBandwidth == 0u && OutgoingBandwidth == 0u)
            {
                peer.WindowSize = MAXIMUM_WINDOW_SIZE;
            }
            else
            {
                peer.WindowSize = (Math.Min(peer.IncomingBandwidth, OutgoingBandwidth) / Peer.WINDOW_SIZE_SCALE) * MINIMUM_WINDOW_SIZE;
            }

            peer.WindowSize = Utils.Clamp(peer.WindowSize, MINIMUM_WINDOW_SIZE, MAXIMUM_WINDOW_SIZE);

            return(0);
        }
Ejemplo n.º 2
0
        public void BandwidthThrottle()
        {
            uint timeCurrent = GetTime();
            uint elapsedTime = timeCurrent - BandwidthThrottleEpoch;

            if (elapsedTime < Version.BandwidthThrottleInterval)
            {
                return;
            }

            uint peersTotal = 0;
            uint dataTotal  = 0;

            foreach (var peer in Peers)
            {
                if (peer.State != PeerState.CONNECTED && peer.State != PeerState.DISCONNECT_LATER)
                {
                    continue;
                }
                peersTotal++;
                dataTotal += peer.OutgoingDataTotal;
            }

            if (peersTotal == 0)
            {
                return;
            }

            uint peersRemaining  = peersTotal;
            bool needsAdjustment = true;

            uint bandwidth = OutgoingBandwidth == 0 ? ~0u : (OutgoingBandwidth * elapsedTime) / 1000u;

            uint throttle = 0;

            while (peersRemaining > 0 && needsAdjustment)
            {
                needsAdjustment = false;

                if (dataTotal < bandwidth)
                {
                    throttle = Peer.PACKET_THROTTLE_SCALE;
                }
                else
                {
                    throttle = (bandwidth * Peer.PACKET_THROTTLE_SCALE) / dataTotal;
                }

                foreach (var peer in Peers)
                {
                    uint peerBandwidth = 0;

                    if ((peer.State != PeerState.CONNECTED && peer.State != PeerState.DISCONNECT_LATER) ||
                        peer.IncomingBandwidth == 0 ||
                        peer.OutgoingBandwidthThrottleEpoch == timeCurrent)
                    {
                        continue;
                    }

                    peerBandwidth = (peer.IncomingBandwidth * elapsedTime) / 1000;

                    if ((throttle * peer.OutgoingDataTotal) / Peer.PACKET_THROTTLE_SCALE <= peerBandwidth)
                    {
                        continue;
                    }

                    peer.PacketThrottleLimit = (peerBandwidth * Peer.PACKET_THROTTLE_SCALE) / peer.OutgoingDataTotal;

                    if (peer.PacketThrottleLimit == 0)
                    {
                        peer.PacketThrottleLimit = 1;
                    }

                    if (peer.PacketThrottle > peer.PacketThrottleLimit)
                    {
                        peer.PacketThrottle = peer.PacketThrottleLimit;
                    }

                    peer.OutgoingBandwidthThrottleEpoch = timeCurrent;

                    needsAdjustment = true;
                    peersRemaining--;
                    bandwidth -= peerBandwidth;
                    dataTotal -= peerBandwidth;
                }
            }

            if (peersRemaining > 0)
            {
                foreach (var peer in Peers)
                {
                    if ((peer.State != PeerState.CONNECTED && peer.State != PeerState.DISCONNECT_LATER) ||
                        peer.OutgoingBandwidthThrottleEpoch == timeCurrent)
                    {
                        continue;
                    }

                    peer.PacketThrottleLimit = throttle;

                    if (peer.PacketThrottle > peer.PacketThrottleLimit)
                    {
                        peer.PacketThrottle = peer.PacketThrottleLimit;
                    }
                }
            }

            if (RecalculateBandwidthLimits)
            {
                RecalculateBandwidthLimits = false;

                peersRemaining  = peersTotal;
                bandwidth       = IncomingBandwidth;
                needsAdjustment = true;

                uint bandwidthLimit = 0;
                if (bandwidth != 0)
                {
                    while (peersRemaining > 0 && needsAdjustment)
                    {
                        needsAdjustment = false;
                        bandwidthLimit  = bandwidth / peersRemaining;

                        foreach (var peer in Peers)
                        {
                            if ((peer.State != PeerState.CONNECTED && peer.State != PeerState.DISCONNECT_LATER) ||
                                peer.IncomingBandwidthThrottleEpoch == timeCurrent)
                            {
                                continue;
                            }

                            if (peer.OutgoingBandwidth > 0 &&
                                peer.OutgoingBandwidth >= bandwidthLimit)
                            {
                                continue;
                            }

                            peer.IncomingBandwidthThrottleEpoch = timeCurrent;

                            needsAdjustment = true;
                            peersRemaining--;
                            bandwidth -= peer.OutgoingBandwidth;
                        }
                    }
                }

                foreach (var peer in Peers)
                {
                    if (peer.State != PeerState.CONNECTED && peer.State != PeerState.DISCONNECT_LATER)
                    {
                        continue;
                    }

                    var command = new Protocol.BandwidthLimit
                    {
                        Flags             = ProtocolFlag.ACKNOWLEDGE,
                        ChannelID         = 0xFF,
                        OutgoingBandwidth = OutgoingBandwidth,
                    };

                    if (peer.IncomingBandwidthThrottleEpoch == timeCurrent)
                    {
                        command.IncomingBandwidth = peer.OutgoingBandwidth;
                    }
                    else
                    {
                        command.IncomingBandwidth = bandwidthLimit;
                    }

                    peer.QueueOutgoingCommand(command, null, 0, 0);
                }
            }

            BandwidthThrottleEpoch = timeCurrent;

            foreach (var peer in Peers)
            {
                peer.IncomingDataTotal = 0;
                peer.OutgoingDataTotal = 0;
            }
        }