Ejemplo n.º 1
0
 def _restore_state(self):
     def decode_line(line):
         hashtext = line[:40]
         try:
             infohash = hashtext.decode('hex')
         except:
             raise BTFailure("Invalid state file contents")
         if len(infohash) != 20:
             raise BTFailure("Invalid state file contents")
         try:
             path = os.path.join(self.config['data_dir'], 'metainfo',
                                 hashtext)
             f = file(path, 'rb')
             data = f.read()
             f.close()
         except Exception, e:
             try:
                 f.close()
             except:
                 pass
             self.global_error("ERROR", "Error reading file %s (%s), \
                         cannot restore state completely" % (path, str(e)))
             return None
         if infohash in self.torrents:
             raise BTFailure("Invalid state file (duplicate entry)")
         t = Torrent(infohash)
         self.torrents[infohash] = t
         try:
             t.metainfo = ConvertedMetainfo(bdecode(data))
         except Exception, e:
             self.global_error("ERROR", "Corrupt data in "+path+
                               " , cannot restore torrent ("+str(e)+")")
             return None
Ejemplo n.º 2
0
 def _restore_state(self):
     def decode_line(line):
         hashtext = line[:40]
         try:
             infohash = hashtext.decode('hex')
         except:
             raise BTFailure("Invalid state file contents")
         if len(infohash) != 20:
             raise BTFailure("Invalid state file contents")
         try:
             path = os.path.join(self.config['data_dir'], 'metainfo',
                                 hashtext)
             f = file(path, 'rb')
             data = f.read()
             f.close()
         except Exception, e:
             try:
                 f.close()
             except:
                 pass
             self.global_error(
                 "ERROR", "Error reading file %s (%s), \
                         cannot restore state completely" % (path, str(e)))
             return None
         if infohash in self.torrents:
             raise BTFailure("Invalid state file (duplicate entry)")
         t = Torrent(infohash)
         self.torrents[infohash] = t
         try:
             t.metainfo = ConvertedMetainfo(bdecode(data))
         except Exception, e:
             self.global_error(
                 "ERROR", "Corrupt data in " + path +
                 " , cannot restore torrent (" + str(e) + ")")
             return None
Ejemplo n.º 3
0
 def start_new_torrent(self, data):
     t = Torrent()
     try:
         t.metainfo = ConvertedMetainfo(bdecode(data))
     except Exception, e:
         self.global_error("ERROR", "This is not a valid torrent file. (%s)"
                           % str(e))
         return
Ejemplo n.º 4
0
 def start_new_torrent(self, data):
     t = Torrent()
     try:
         t.metainfo = ConvertedMetainfo(bdecode(data))
     except Exception, e:
         self.global_error(
             "ERROR", "This is not a valid torrent file. (%s)" % str(e))
         return
Ejemplo n.º 5
0
class _SingleTorrent(object):

    def __init__(self, event_handler, singleport_listener, ratelimiter, filepool,
                 config, neighbors, certificate, sessionid):
        self.event_handler = event_handler
        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._torrent = 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.file_size = 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.messages = []
        self.neighbors = neighbors
        self.certificate = certificate
        self.sessionid = sessionid

    def schedule(self, delay, func):
        self.event_handler.schedule(delay, func, context=self)

    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.schedule(0, cont)
        self._contfunc = contfunc
        contfunc()

    def _start_download(self, metainfo, feedback, save_path):
    
        # GTK Crash Hack
        import time
        time.sleep(.2)
        
        self.feedback = feedback
        self._set_auto_uploads()

        self.infohash = metainfo.infohash
        self.file_size = metainfo.file_size
        if not metainfo.reported_errors:
            metainfo.show_encoding_errors(log.error)

        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(self.config, self._filepool, zip(myfiles,
                                                            metainfo.sizes))
        resumefile = None
        if self.config['data_dir']:
            filename = os.path.join(self.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:
                    log.info("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)
            log.info('piece %d failed hash check, '
                        're-downloading it' % index)
        backthread_exception = None
        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,
                     self.config, metainfo.hashes, metainfo.piece_length,
                     self._finished, statusfunc, self._doneflag, data_flunked,
                     self.infohash, resumefile)
            except:
                backthread_exception = sys.exc_info()
            self._contfunc()
        thread = threading.Thread(target = hashcheck)
        thread.setDaemon(False)
        self._hashcheck_thread = thread
        thread.start()
        yield None
        self._hashcheck_thread = None
        if resumefile is not None:
            resumefile.close()
        if backthread_exception:
            a, b, c = backthread_exception
            raise a, b, c

        if self._storagewrapper.amount_left == 0:
            self._finished()
        choker = Choker(self.config, self.schedule, self.finflag.isSet)
        upmeasure = Measure(self.config['max_rate_period'])
        downmeasure = Measure(self.config['max_rate_period'])
        self._upmeasure = upmeasure
        self._downmeasure = downmeasure
        self._ratemeasure = RateMeasure(self._storagewrapper.
                                        amount_left_with_partials)
        picker = PiecePicker(len(metainfo.hashes), self.config)
        for i in xrange(len(metainfo.hashes)):
            if self._storagewrapper.do_I_have(i):
                picker.complete(i)
        for i in self._storagewrapper.stat_dirty:
            picker.requested(i)
        def kickpeer(connection):
            def kick():
                connection.close()
            self.schedule(0, kick)
        downloader = Downloader(self.config, self._storagewrapper, picker,
                                len(metainfo.hashes), downmeasure,
                                self._ratemeasure.data_came_in, kickpeer)
        def make_upload(connection):
            return Upload(connection, self._ratelimiter, upmeasure, choker,
                    self._storagewrapper, self.config['max_slice_length'],
                    self.config['max_rate_period'])
        self._torrent = Torrent(self.infohash, make_upload,
                                downloader, len(metainfo.hashes), self)
        self.reported_port = self.config['forwarded_port']
        if not self.reported_port:
            self.reported_port = self._singleport_listener.get_port(self.neighbors)
            self.reserved_ports.append(self.reported_port)
        self.neighbors.add_torrent(self.infohash, self._torrent)
        self._listening = True
        self._rerequest = Rerequester(metainfo.announce, self.config,
            self.schedule, self.neighbors, self._storagewrapper.get_amount_left,
            upmeasure.get_total, downmeasure.get_total, self.reported_port,
            self.infohash, self.finflag, self.internal_shutdown,
            self._announce_done, self.certificate, self.sessionid)
        self._statuscollecter = DownloaderFeedback(choker, upmeasure.get_rate,
            downmeasure.get_rate, upmeasure.get_total, downmeasure.get_total,
            self.neighbors.get_relay_stats, self._ratemeasure.get_time_left,
            self._ratemeasure.get_size_left, self.file_size, self.finflag,
            downloader, self._myfiles)

        self._announced = True
        self._rerequest.begin()
        self.started = True
        if not self.finflag.isSet():
            self._activity = ('downloading', 0)
        self.feedback.started(self)