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

📄 download.py

📁 BT的原代码
💻 PY
📖 第 1 页 / 共 2 页
字号:
# The contents of this file are subject to the BitTorrent Open Source License# Version 1.0 (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 and Uoti Urpalafrom __future__ import division# required for python 2.2from __future__ import generatorsimport osimport sysimport threadingimport errnoimport gcfrom sha import shafrom socket import error as socketerrorfrom random import seedfrom time import timefrom cStringIO import StringIOfrom traceback import print_excfrom math import sqrttry:    getpid = os.getpidexcept AttributeError:    def getpid():        return 1from BitTorrent.btformats import check_messagefrom BitTorrent.Choker import Chokerfrom BitTorrent.Storage import Storage, FilePoolfrom BitTorrent.StorageWrapper import StorageWrapperfrom BitTorrent.Uploader import Uploadfrom BitTorrent.Downloader import Downloaderfrom BitTorrent.Encoder import Encoder, SingleportListenerfrom BitTorrent.RateLimiter import RateLimiterfrom BitTorrent.RawServer import RawServerfrom BitTorrent.Rerequester import Rerequesterfrom BitTorrent.DownloaderFeedback import DownloaderFeedbackfrom BitTorrent.RateMeasure import RateMeasurefrom BitTorrent.CurrentRateMeasure import Measurefrom BitTorrent.PiecePicker import PiecePickerfrom BitTorrent.ConvertedMetainfo import set_filesystem_encodingfrom BitTorrent import versionfrom BitTorrent import BTFailure, BTShutdown, INFO, WARNING, ERROR, CRITICALclass Feedback(object):    def finished(self, torrent):        pass    def failed(self, torrent, is_external):        pass    def error(self, torrent, level, text):        pass    def exception(self, torrent, text):        self.error(torrent, CRITICAL, text)    def started(self, torrent):        passclass Multitorrent(object):    def __init__(self, config, doneflag, errorfunc, listen_fail_ok=False):        self.config = dict(config)        self.errorfunc = errorfunc        self.rawserver = RawServer(doneflag, config, errorfunc=errorfunc,                                   tos=config['peer_socket_tos'])        self.singleport_listener = SingleportListener(self.rawserver)        self._find_port(listen_fail_ok)        self.filepool = FilePool(config['max_files_open'])        self.ratelimiter = RateLimiter(self.rawserver.add_task)        self.ratelimiter.set_parameters(config['max_upload_rate'],                                        config['upload_unit_size'])        set_filesystem_encoding(config['filesystem_encoding'],                                                 errorfunc)    def _find_port(self, listen_fail_ok=True):        e = 'maxport less than minport - no ports to check'        if self.config['minport'] <= 0:            self.config['minport'] = 1        for port in xrange(self.config['minport'], self.config['maxport'] + 1):            try:                self.singleport_listener.open_port(port, self.config)                break            except socketerror, e:                pass        else:            if not listen_fail_ok:                raise BTFailure, "Couldn't open a listening port: " + str(e)            self.errorfunc(CRITICAL, "Could not open a listening port: " +                           str(e) + ". Check your port range settings.")    def close_listening_socket(self):        self.singleport_listener.close_sockets()    def start_torrent(self, metainfo, config, feedback, filename):        torrent = _SingleTorrent(self.rawserver, self.singleport_listener,                                 self.ratelimiter, self.filepool, config)        self.rawserver.add_context(torrent)        def start():            torrent.start_download(metainfo, feedback, filename)        self.rawserver.add_task(start, 0, torrent)        return torrent    def set_option(self, option, value):        if option not in self.config or self.config[option] == value:            return        if option not in 'max_upload_rate upload_unit_size '\               'max_files_open minport maxport'.split():            return        self.config[option] = value        if option == 'max_files_open':            self.filepool.set_max_files_open(value)        elif option == 'max_upload_rate':            self.ratelimiter.set_parameters(value,                                            self.config['upload_unit_size'])        elif option == 'upload_unit_size':            self.ratelimiter.set_parameters(self.config['max_upload_rate'],                                            value)        elif option == 'maxport':            if not self.config['minport'] <= self.singleport_listener.port <= \                   self.config['maxport']:                self._find_port()    def get_completion(self, config, metainfo, save_path, filelist=False):        if not config['data_dir']:            return None        infohash = metainfo.infohash        if metainfo.is_batch:            myfiles = [os.path.join(save_path, f) for f in metainfo.files_fs]        else:            myfiles = [save_path]        if metainfo.total_bytes == 0:            if filelist:                return None            return 1        try:            s = Storage(None, None, zip(myfiles, metainfo.sizes),                        check_only=True)        except:            return None        filename = os.path.join(config['data_dir'], 'resume',                                infohash.encode('hex'))        try:            f = file(filename, 'rb')        except:            f = None        try:            r = s.check_fastresume(f, filelist, metainfo.piece_length,                                   len(metainfo.hashes), myfiles)        except:            r = None        if f is not None:            f.close()        if r is None:            return None        if filelist:            return r[0] / metainfo.total_bytes, r[1], r[2]        return r / metainfo.total_bytesclass _SingleTorrent(object):    def __init__(self, rawserver, singleport_listener, ratelimiter, filepool,                 config):        self._rawserver = rawserver        self._singleport_listener = singleport_listener        self._ratelimiter = ratelimiter        self._filepool = filepool        self.config = dict(config)        self._storage = None        self._storagewrapper = None        self._ratemeasure = None        self._upmeasure = None        self._downmeasure = None        self._encoder = None        self._rerequest = None        self._statuscollecter = None        self._announced = False        self._listening = False        self.reserved_ports = []        self.reported_port = None        self._myfiles = None        self.started = False        self.is_seed = False        self.closed = False        self.infohash = None        self.total_bytes = None        self._doneflag = threading.Event()        self.finflag = threading.Event()        self._hashcheck_thread = None        self._contfunc = None        self._activity = ('Initial startup', 0)        self.feedback = None        self.errors = []    def start_download(self, *args, **kwargs):        it = self._start_download(*args, **kwargs)        def cont():            try:                it.next()            except StopIteration:                self._contfunc = None        def contfunc():            self._rawserver.external_add_task(cont, 0, self)        self._contfunc = contfunc        contfunc()    def _start_download(self, metainfo, feedback, save_path):        self.feedback = feedback        config = self.config        self._set_auto_uploads()        self.infohash = metainfo.infohash        self.total_bytes = metainfo.total_bytes        if not metainfo.reported_errors:            metainfo.show_encoding_errors(self._error)        myid = self._make_id()        seed(myid)        def schedfunc(func, delay):            self._rawserver.add_task(func, delay, self)        def externalsched(func, delay):            self._rawserver.external_add_task(func, delay, self)        if metainfo.is_batch:            myfiles = [os.path.join(save_path, f) for f in metainfo.files_fs]        else:            myfiles = [save_path]        self._filepool.add_files(myfiles, self)        self._myfiles = myfiles        self._storage = Storage(config, self._filepool, zip(myfiles,                                                            metainfo.sizes))        resumefile = None        if config['data_dir']:            filename = os.path.join(config['data_dir'], 'resume',                                    self.infohash.encode('hex'))            if os.path.exists(filename):                try:                    resumefile = file(filename, 'rb')                    if self._storage.check_fastresume(resumefile) == 0:                        resumefile.close()                        resumefile = None                except Exception, e:                    self._error(WARNING, 'Could not load fastresume data: '+                                str(e) + '. Will perform full hash check.')                    if resumefile is not None:                        resumefile.close()                    resumefile = None        def data_flunked(amount, index):            self._ratemeasure.data_rejected(amount)            self._error(INFO, 'piece %d failed hash check, '                        're-downloading it' % index)        backthread_exception = []        def errorfunc(level, text):            def e():                self._error(level, text)            externalsched(e, 0)        def hashcheck():            def statusfunc(activity = None, fractionDone = 0):                if activity is None:                    activity = self._activity[0]                self._activity = (activity, fractionDone)            try:                self._storagewrapper = StorageWrapper(self._storage,                     config, metainfo.hashes, metainfo.piece_length,                     self._finished, statusfunc, self._doneflag, data_flunked,

⌨️ 快捷键说明

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