forked from LBRYCommunity/lbry-sdk
206 lines
6.1 KiB
Python
206 lines
6.1 KiB
Python
|
from zope.interface import implements
|
||
|
from lbrynet.interfaces import IRateLimiter
|
||
|
|
||
|
|
||
|
class DummyRateLimiter(object):
|
||
|
def __init__(self):
|
||
|
self.dl_bytes_this_second = 0
|
||
|
self.ul_bytes_this_second = 0
|
||
|
self.total_dl_bytes = 0
|
||
|
self.total_ul_bytes = 0
|
||
|
self.target_dl = 0
|
||
|
self.target_ul = 0
|
||
|
self.ul_delay = 0.00
|
||
|
self.dl_delay = 0.00
|
||
|
self.next_tick = None
|
||
|
|
||
|
def tick(self):
|
||
|
|
||
|
from twisted.internet import reactor
|
||
|
|
||
|
self.dl_bytes_this_second = 0
|
||
|
self.ul_bytes_this_second = 0
|
||
|
self.next_tick = reactor.callLater(1.0, self.tick)
|
||
|
|
||
|
def stop(self):
|
||
|
if self.next_tick is not None:
|
||
|
self.next_tick.cancel()
|
||
|
self.next_tick = None
|
||
|
|
||
|
def set_dl_limit(self, limit):
|
||
|
pass
|
||
|
|
||
|
def set_ul_limit(self, limit):
|
||
|
pass
|
||
|
|
||
|
def ul_wait_time(self):
|
||
|
return self.ul_delay
|
||
|
|
||
|
def dl_wait_time(self):
|
||
|
return self.dl_delay
|
||
|
|
||
|
def report_dl_bytes(self, num_bytes):
|
||
|
self.dl_bytes_this_second += num_bytes
|
||
|
self.total_dl_bytes += num_bytes
|
||
|
|
||
|
def report_ul_bytes(self, num_bytes):
|
||
|
self.ul_bytes_this_second += num_bytes
|
||
|
self.total_ul_bytes += num_bytes
|
||
|
|
||
|
|
||
|
class RateLimiter(object):
|
||
|
"""This class ensures that upload and download rates don't exceed specified maximums"""
|
||
|
|
||
|
implements(IRateLimiter)
|
||
|
|
||
|
#called by main application
|
||
|
|
||
|
def __init__(self, max_dl_bytes=None, max_ul_bytes=None):
|
||
|
self.max_dl_bytes = max_dl_bytes
|
||
|
self.max_ul_bytes = max_ul_bytes
|
||
|
self.dl_bytes_this_second = 0
|
||
|
self.ul_bytes_this_second = 0
|
||
|
self.total_dl_bytes = 0
|
||
|
self.total_ul_bytes = 0
|
||
|
self.next_tick = None
|
||
|
self.next_unthrottle_dl = None
|
||
|
self.next_unthrottle_ul = None
|
||
|
|
||
|
self.next_dl_check = None
|
||
|
self.next_ul_check = None
|
||
|
|
||
|
self.dl_check_interval = 1.0
|
||
|
self.ul_check_interval = 1.0
|
||
|
|
||
|
self.dl_throttled = False
|
||
|
self.ul_throttled = False
|
||
|
|
||
|
self.protocols = []
|
||
|
|
||
|
def tick(self):
|
||
|
|
||
|
from twisted.internet import reactor
|
||
|
|
||
|
# happens once per second
|
||
|
if self.next_dl_check is not None:
|
||
|
self.next_dl_check.cancel()
|
||
|
self.next_dl_check = None
|
||
|
if self.next_ul_check is not None:
|
||
|
self.next_ul_check.cancel()
|
||
|
self.next_ul_check = None
|
||
|
if self.max_dl_bytes is not None:
|
||
|
if self.dl_bytes_this_second == 0:
|
||
|
self.dl_check_interval = 1.0
|
||
|
else:
|
||
|
self.dl_check_interval = min(1.0, self.dl_check_interval *
|
||
|
self.max_dl_bytes / self.dl_bytes_this_second)
|
||
|
self.next_dl_check = reactor.callLater(self.dl_check_interval, self.check_dl)
|
||
|
if self.max_ul_bytes is not None:
|
||
|
if self.ul_bytes_this_second == 0:
|
||
|
self.ul_check_interval = 1.0
|
||
|
else:
|
||
|
self.ul_check_interval = min(1.0, self.ul_check_interval *
|
||
|
self.max_ul_bytes / self.ul_bytes_this_second)
|
||
|
self.next_ul_check = reactor.callLater(self.ul_check_interval, self.check_ul)
|
||
|
self.dl_bytes_this_second = 0
|
||
|
self.ul_bytes_this_second = 0
|
||
|
self.unthrottle_dl()
|
||
|
self.unthrottle_ul()
|
||
|
self.next_tick = reactor.callLater(1.0, self.tick)
|
||
|
|
||
|
def stop(self):
|
||
|
if self.next_tick is not None:
|
||
|
self.next_tick.cancel()
|
||
|
self.next_tick = None
|
||
|
if self.next_dl_check is not None:
|
||
|
self.next_dl_check.cancel()
|
||
|
self.next_dl_check = None
|
||
|
if self.next_ul_check is not None:
|
||
|
self.next_ul_check.cancel()
|
||
|
self.next_ul_check = None
|
||
|
|
||
|
def set_dl_limit(self, limit):
|
||
|
self.max_dl_bytes = limit
|
||
|
|
||
|
def set_ul_limit(self, limit):
|
||
|
self.max_ul_bytes = limit
|
||
|
|
||
|
#throttling
|
||
|
|
||
|
def check_dl(self):
|
||
|
|
||
|
from twisted.internet import reactor
|
||
|
|
||
|
self.next_dl_check = None
|
||
|
|
||
|
if self.dl_bytes_this_second > self.max_dl_bytes:
|
||
|
self.throttle_dl()
|
||
|
else:
|
||
|
self.next_dl_check = reactor.callLater(self.dl_check_interval, self.check_dl)
|
||
|
self.dl_check_interval = min(self.dl_check_interval * 2, 1.0)
|
||
|
|
||
|
def check_ul(self):
|
||
|
|
||
|
from twisted.internet import reactor
|
||
|
|
||
|
self.next_ul_check = None
|
||
|
|
||
|
if self.ul_bytes_this_second > self.max_ul_bytes:
|
||
|
self.throttle_ul()
|
||
|
else:
|
||
|
self.next_ul_check = reactor.callLater(self.ul_check_interval, self.check_ul)
|
||
|
self.ul_check_interval = min(self.ul_check_interval * 2, 1.0)
|
||
|
|
||
|
def throttle_dl(self):
|
||
|
if self.dl_throttled is False:
|
||
|
for protocol in self.protocols:
|
||
|
protocol.throttle_download()
|
||
|
self.dl_throttled = True
|
||
|
|
||
|
def throttle_ul(self):
|
||
|
if self.ul_throttled is False:
|
||
|
for protocol in self.protocols:
|
||
|
protocol.throttle_upload()
|
||
|
self.ul_throttled = True
|
||
|
|
||
|
def unthrottle_dl(self):
|
||
|
if self.dl_throttled is True:
|
||
|
for protocol in self.protocols:
|
||
|
protocol.unthrottle_download()
|
||
|
self.dl_throttled = False
|
||
|
|
||
|
def unthrottle_ul(self):
|
||
|
if self.ul_throttled is True:
|
||
|
for protocol in self.protocols:
|
||
|
protocol.unthrottle_upload()
|
||
|
self.ul_throttled = False
|
||
|
|
||
|
#deprecated
|
||
|
|
||
|
def ul_wait_time(self):
|
||
|
return 0
|
||
|
|
||
|
def dl_wait_time(self):
|
||
|
return 0
|
||
|
|
||
|
#called by protocols
|
||
|
|
||
|
def report_dl_bytes(self, num_bytes):
|
||
|
self.dl_bytes_this_second += num_bytes
|
||
|
self.total_dl_bytes += num_bytes
|
||
|
|
||
|
def report_ul_bytes(self, num_bytes):
|
||
|
self.ul_bytes_this_second += num_bytes
|
||
|
self.total_ul_bytes += num_bytes
|
||
|
|
||
|
def register_protocol(self, protocol):
|
||
|
if protocol not in self.protocols:
|
||
|
self.protocols.append(protocol)
|
||
|
if self.dl_throttled is True:
|
||
|
protocol.throttle_download()
|
||
|
if self.ul_throttled is True:
|
||
|
protocol.throttle_upload()
|
||
|
|
||
|
def unregister_protocol(self, protocol):
|
||
|
if protocol in self.protocols:
|
||
|
self.protocols.remove(protocol)
|