⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 download.py

📁 bittorrent source by python. please enjoy
💻 PY
📖 第 1 页 / 共 2 页
字号:
# The contents of this file are subject to the BitTorrent Open Source License# Version 1.1 (the License).  You may not copy or use this file, in either# source code or executable form, except in compliance with the License.  You# may obtain a copy of the License at http://www.bittorrent.com/license/.## Software distributed under the License is distributed on an AS IS basis,# WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License# for the specific language governing rights and limitations under the# License.# Written by Bram Cohen, Uoti Urpala, David Harrison, and Greg Hazelimport randomimport loggingfrom BitTorrent.obsoletepythonsupport import *from BitTorrent.platform import bttimefrom BitTorrent.CurrentRateMeasure import Measurefrom BitTorrent.bitfield import Bitfieldfrom BitTorrent.defer import Deferredlogger = logging.getLogger("BitTorrent.Download")log = logger.debugclass BadDataGuard(object):    def __init__(self, download):        self.download = download        self.ip = download.connection.ip        self.multidownload = download.multidownload        self.stats = self.multidownload.perip[self.ip]        self.lastindex = None    def bad(self, index, bump = False):        self.stats.bad.setdefault(index, 0)        self.stats.bad[index] += 1        if self.ip not in self.multidownload.bad_peers:            self.multidownload.bad_peers[self.ip] = (False, self.stats)        if self.download is not None:            self.multidownload.kick(self.download)            self.download = None        elif len(self.stats.bad) > 1 and self.stats.numconnections == 1 and \             self.stats.lastdownload is not None:            # kick new connection from same IP if previous one sent bad data,            # mainly to give the algorithm time to find other bad pieces            # in case the peer is sending a lot of bad data            self.multidownload.kick(self.stats.lastdownload)        if len(self.stats.bad) >= 3 and len(self.stats.bad) > \           self.stats.numgood // 30:            self.multidownload.ban(self.ip)        elif bump:            self.multidownload.active_requests.remove(index)            self.multidownload.picker.bump(index)    def good(self, index):        # lastindex is a hack to only increase numgood for by one for each good        # piece, however many chunks came from the connection(s) from this IP        if index != self.lastindex:            self.stats.numgood += 1            self.lastindex = indexclass Download(object):    """Implements BitTorrent protocol semantics for downloading over a single       connection.  See Upload for the protocol semantics in the upload       direction.  See Connector.Connection for the protocol syntax       implementation."""    def __init__(self, multidownload, connection):        self.multidownload = multidownload        self.connection = connection        self.choked = True        self.interested = False        self.prefer_full = False        self.active_requests = set()        self.measure = Measure(multidownload.config['max_rate_period'])        self.peermeasure = Measure(            max(multidownload.storage.piece_size / 10000, 20))        self.have = Bitfield(multidownload.numpieces)        self.last = 0        self.example_interest = None        self.guard = BadDataGuard(self)        self.suggested_pieces = []        self.allowed_fast_pieces = []            def _backlog(self):        backlog = 2 + int(4 * self.measure.get_rate() /                          self.multidownload.chunksize)        if backlog > 50:            backlog = max(50, int(.075 * backlog))        return backlog    def disconnected(self):        self.multidownload.lost_peer(self)        if self.have.numfalse == 0:            self.multidownload.lost_have_all()        else:            # arg, slow            count = 0            target = len(self.have) - self.have.numfalse            for i in xrange(len(self.have)):                if count == target:                    break                if self.have[i]:                    self.multidownload.lost_have(i)                    count += 1        self._letgo()        self.guard.download = None            def _letgo(self):        if not self.active_requests:            return        if self.multidownload.storage.endgame:            self.active_requests.clear()            return        lost = []        for index, begin, length in self.active_requests:            self.multidownload.storage.request_lost(index, begin, length)            self.multidownload.active_requests.remove(index)            if index not in lost:                lost.append(index)        self.active_requests.clear()        ds = [d for d in self.multidownload.downloads if not d.choked]        random.shuffle(ds)        for d in ds:            d._request_more(lost)        for d in self.multidownload.downloads:            if d.choked and not d.interested:                for l in lost:                    if d.have[l] and \                      self.multidownload.storage.want_requests(l):                        d.interested = True                        d.connection.send_interested()                        break            def got_choke(self):        if not self.choked:            self.choked = True            if not self.connection.uses_fast_extension:                self._letgo()            def got_unchoke(self):        if self.choked:            self.choked = False            if self.interested:                self._request_more()    def got_piece(self, index, begin, piece):        req = (index, begin, len(piece))        if req not in self.active_requests:            self.multidownload.discarded_bytes += len(piece)            if self.connection.uses_fast_extension:                self.connection.close()            return                self.active_requests.remove(req)                if self.multidownload.storage.endgame:            if req not in self.multidownload.all_requests:                self.multidownload.discarded_bytes += len(piece)                return                        self.multidownload.all_requests.remove(req)            for d in self.multidownload.downloads:                if d.interested:                    if not d.choked:                        if req in d.active_requests:                            d.connection.send_cancel(*req)                            if not self.connection.uses_fast_extension:                                d.active_requests.remove(req)                    d.fix_download_endgame()        else:            self._request_more()                    self.last = bttime()        self.update_rate(len(piece))        df = self.multidownload.storage.write(index, begin, piece, self.guard)        df.addCallback(self._got_piece, index)    def _got_piece(self, hashchecked, index):        if hashchecked:            self.multidownload.hashchecked(index)            def _want(self, index):        return self.have[index] and \               self.multidownload.storage.want_requests(index)    def _request_more(self, indices = []):                if self.choked:            self._request_when_choked()            return        #log( "_request_more.active_requests=%s" % self.active_requests )        b = self._backlog()        if len(self.active_requests) >= b:            return        if self.multidownload.storage.endgame:            self.fix_download_endgame()            return        self.suggested_pieces = [i for i in self.suggested_pieces             if not self.multidownload.storage.do_I_have(i)]        lost_interests = []        while len(self.active_requests) < b:            if not indices:                interest = self.multidownload.picker.next(self.have,                                    self.multidownload.active_requests,                                    self.multidownload.storage.full_pieces,                                    self.suggested_pieces)            else:                interest = None                for i in indices:                    if self.have[i] and \                            self.multidownload.storage.want_requests(i):                        interest = i                        break            if interest is None:                break            if not self.interested:                self.interested = True                self.connection.send_interested()            # an example interest created by from_behind is preferable            if self.example_interest is None:                self.example_interest = interest            # request as many chunks of interesting piece as fit in backlog.            while len(self.active_requests) < b:                begin, length = self.multidownload.storage.new_request(interest,                                                                       self.prefer_full)                self.multidownload.active_requests_add(interest)                self.active_requests.add((interest, begin, length))                self.connection.send_request(interest, begin, length)                if not self.multidownload.storage.want_requests(interest):                    lost_interests.append(interest)                    break        if not self.active_requests and self.interested:            self.interested = False            self.connection.send_not_interested()        self._check_lost_interests(lost_interests)        if self.multidownload.storage.endgame:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -