Exemple #1
0
 def __init__(self, downloader, connection):
     self.downloader = downloader
     self.connection = connection
     self.choked = True
     self.interested = False
     self.active_requests = []
     self.measure = Measure(downloader.config['max_rate_period'])
     self.peermeasure = Measure(max(downloader.storage.piece_size / 10000,
                                    20))
     self.have = Bitfield(downloader.numpieces)
     self.last = 0
     self.example_interest = None
     self.backlog = 2
     self.guard = BadDataGuard(self)
Exemple #2
0
 def __init__(self, downloader, connection):
     self.downloader = downloader
     self.connection = connection
     self.choked = True
     self.interested = False
     self.active_requests = []
     self.measure = Measure(downloader.max_rate_period)
     self.peermeasure = Measure(downloader.max_rate_period)
     self.have = Bitfield(downloader.numpieces)
     self.last = -1000
     self.last2 = -1000
     self.example_interest = None
     #        self.backlog = 2
     self.backlog = 8
     self.ip = connection.get_ip()
     self.guard = BadDataGuard(self)
Exemple #3
0
 def got_message(self, protocol, message):
     c = self.connections[protocol]
     t = message[0]
     log_msg('%s message received %s' % (c.ccount, ord(t)), 4, "btprotocol")
     if t == BITFIELD and c.got_anything:
         log_msg('%s misplaced bitfield' % (c.ccount), 0, "btprotocol")
         protocol.close()
         return
     c.got_anything = True
     if (t in [CHOKE, UNCHOKE, INTERESTED, NOT_INTERESTED]
             and len(message) != 1):
         log_msg('%s bad message length' % (c.ccount), 0, "btprotocol")
         protocol.close()
         return
     if t == CHOKE:
         c.download.got_choke()
     elif t == UNCHOKE:
         c.download.got_unchoke()
     elif t == INTERESTED:
         if not c.download.have.complete():
             c.upload.got_interested()
     elif t == NOT_INTERESTED:
         c.upload.got_not_interested()
     elif t == HAVE:
         if len(message) != 5:
             log_msg('%s bad message length (HAVE)' % (c.ccount), 0,
                     "btprotocol")
             protocol.close()
             return
         i = toint(message[1:])
         if i >= self.numpieces:
             log_msg('%s bad piece number (HAVE)' % (c.ccount), 0,
                     "btprotocol")
             protocol.close()
             return
         if c.download.got_have(i):
             c.upload.got_not_interested()
     elif t == BITFIELD:
         try:
             b = Bitfield(self.numpieces, message[1:])
         except ValueError:
             log_msg('%s bad bitfield' % (c.ccount), 0, "btprotocol")
             protocol.close()
             return
         if c.download.got_have_bitfield(b):
             c.upload.got_not_interested()
     elif t == REQUEST:
         if len(message) != 13:
             log_msg('%s bad message length (REQUEST)' % (c.ccount), 0,
                     "btprotocol")
             protocol.close()
             return
         i = toint(message[1:5])
         if i >= self.numpieces:
             log_msg('%s bad piece number (REQUEST)' % (c.ccount), 0,
                     "btprotocol")
             protocol.close()
             return
         c.got_request(i, toint(message[5:9]), toint(message[9:]))
     elif t == CANCEL:
         if len(message) != 13:
             log_msg('%s bad message length (CANCEL)' % (c.ccount), 0,
                     "btprotocol")
             protocol.close()
             return
         i = toint(message[1:5])
         if i >= self.numpieces:
             log_msg('%s bad piece number (CANCEL)' % (c.ccount), 0,
                     "btprotocol")
             protocol.close()
             return
         c.upload.got_cancel(i, toint(message[5:9]), toint(message[9:]))
     elif t == PIECE:
         if len(message) <= 9:
             log_msg('%s bad message length (PIECE)' % (c.ccount), 0,
                     "btprotocol")
             protocol.close()
             return
         i = toint(message[1:5])
         if i >= self.numpieces:
             log_msg('%s bad piece number (PIECE)' % (c.ccount), 0,
                     "btprotocol")
             protocol.close()
             return
         if c.download.got_piece(i, toint(message[5:9]), message[9:]):
             c.lastActive = time.time()
             self.got_piece(i)
     else:
         protocol.close()
Exemple #4
0
    def __init__(self, storage, config, hashes, piece_size, finished,
            statusfunc, flag, data_flunked, infohash, errorfunc, resumefile):
        self.numpieces = len(hashes)
        self.storage = storage
        self.config = config
        check_hashes = config['check_hashes']
        self.hashes = hashes
        self.piece_size = piece_size
        self.data_flunked = data_flunked
        self.errorfunc = errorfunc
        self.total_length = storage.get_total_length()
        self.amount_left = self.total_length
        self.partial_mark = "BitTorrent - this part has not been "+\
                            "downloaded yet."+infohash+\
                            tobinary(config['download_slice_size'])
        if self.total_length <= piece_size * (self.numpieces - 1):
            raise BTFailure, _("bad data in responsefile - total too small")
        if self.total_length > piece_size * self.numpieces:
            raise BTFailure, _("bad data in responsefile - total too big")
        self.finished = finished
        self.numactive = array('H', [0] * self.numpieces)
        self.inactive_requests = [1] * self.numpieces
        self.amount_inactive = self.total_length
        self.endgame = False
        self.have = Bitfield(self.numpieces)
        self.waschecked = Bitfield(self.numpieces)
        if self.numpieces < 32768:
            typecode = 'h'
        else:
            typecode = 'l'
        self.places = array(typecode, [NO_PLACE] * self.numpieces)
        if not check_hashes:
            self.rplaces = array(typecode, range(self.numpieces))
            fastresume = True
        else:
            self.rplaces = self._load_fastresume(resumefile, typecode)
            if self.rplaces is not None:
                fastresume = True
            else:
                self.rplaces = array(typecode, [UNALLOCATED] * self.numpieces)
                fastresume = False
        self.holepos = 0
        self.stat_numfound = 0
        self.stat_numflunked = 0
        self.stat_numdownloaded = 0
        self.stat_active = {}
        self.stat_new = {}
        self.stat_dirty = {}
        self.download_history = {}
        self.failed_pieces = {}

        if self.numpieces == 0:
            return
        targets = {}
        total = 0
        if not fastresume:
            for i in xrange(self.numpieces):
                if self._waspre(i):
                    self.rplaces[i] = ALLOCATED
                    total += 1
                else:
                    targets[hashes[i]] = i
        if total and check_hashes:
            statusfunc(_("checking existing file"), 0)
        def markgot(piece, pos):
            if self.have[piece]:
                if piece != pos:
                    return
                self.rplaces[self.places[pos]] = ALLOCATED
                self.places[pos] = self.rplaces[pos] = pos
                return
            self.places[piece] = pos
            self.rplaces[pos] = piece
            self.have[piece] = True
            self.amount_left -= self._piecelen(piece)
            self.amount_inactive -= self._piecelen(piece)
            self.inactive_requests[piece] = None
            if not fastresume:
                self.waschecked[piece] = True
            self.stat_numfound += 1
        lastlen = self._piecelen(self.numpieces - 1)
        partials = {}
        for i in xrange(self.numpieces):
            if not self._waspre(i):
                if self.rplaces[i] != UNALLOCATED:
                    raise BTFailure(_("--check_hashes 0 or fastresume info "
                                      "doesn't match file state (missing data)"))
                continue
            elif fastresume:
                t = self.rplaces[i]
                if t >= 0:
                    markgot(t, i)
                    continue
                if t == UNALLOCATED:
                    raise BTFailure(_("Bad fastresume info (files contain more "
                                      "data)"))
                if t == ALLOCATED:
                    continue
                if t!= FASTRESUME_PARTIAL:
                    raise BTFailure(_("Bad fastresume info (illegal value)"))
                data = self.storage.read(self.piece_size * i,
                                         self._piecelen(i))
                self._check_partial(i, partials, data)
                self.rplaces[i] = ALLOCATED
            else:
                data = self.storage.read(piece_size * i, self._piecelen(i))
                sh = sha(buffer(data, 0, lastlen))
                sp = sh.digest()
                sh.update(buffer(data, lastlen))
                s = sh.digest()
                if s == hashes[i]:
                    markgot(i, i)
                elif s in targets and self._piecelen(i) == self._piecelen(targets[s]):
                    markgot(targets[s], i)
                elif not self.have[self.numpieces - 1] and sp == hashes[-1] and (i == self.numpieces - 1 or not self._waspre(self.numpieces - 1)):
                    markgot(self.numpieces - 1, i)
                else:
                    self._check_partial(i, partials, data)
                statusfunc(fractionDone = 1 - self.amount_left /
                           self.total_length)
            if flag.isSet():
                return
        self.amount_left_with_partials = self.amount_left
        for piece in partials:
            if self.places[piece] < 0:
                pos = partials[piece][0]
                self.places[piece] = pos
                self.rplaces[pos] = piece
                self._make_partial(piece, partials[piece][1])
        for i in xrange(self.numpieces):
            if self.rplaces[i] != UNALLOCATED:
                self.storage.allocated(piece_size * i, self._piecelen(i))
            if self.have[i]:
                self.storage.downloaded(piece_size * i, self._piecelen(i))
Exemple #5
0
 def _got_message(self, message):
     t = message[0]
     if t == BITFIELD and self.got_anything:
         self.close()
         return
     self.got_anything = True
     if (t in [CHOKE, UNCHOKE, INTERESTED, NOT_INTERESTED]
             and len(message) != 1):
         self.close()
         return
     if t == CHOKE:
         self.download.got_choke()
     elif t == UNCHOKE:
         self.download.got_unchoke()
     elif t == INTERESTED:
         self.upload.got_interested()
     elif t == NOT_INTERESTED:
         self.upload.got_not_interested()
     elif t == HAVE:
         if len(message) != 5:
             self.close()
             return
         i = unpack("!xi", message)[0]
         if i >= self.encoder.numpieces:
             self.close()
             return
         self.download.got_have(i)
     elif t == BITFIELD:
         try:
             b = Bitfield(self.encoder.numpieces, message[1:])
         except ValueError:
             self.close()
             return
         self.download.got_have_bitfield(b)
     elif t == REQUEST:
         if len(message) != 13:
             self.close()
             return
         i, a, b = unpack("!xiii", message)
         if i >= self.encoder.numpieces:
             self.close()
             return
         self.upload.got_request(i, a, b)
     elif t == CANCEL:
         if len(message) != 13:
             self.close()
             return
         i, a, b = unpack("!xiii", message)
         if i >= self.encoder.numpieces:
             self.close()
             return
         self.upload.got_cancel(i, a, b)
     elif t == PIECE:
         if len(message) <= 9:
             self.close()
             return
         n = len(message) - 9
         i, a, b = unpack("!xii%ss" % n, message)
         if i >= self.encoder.numpieces:
             self.close()
             return
         if self.download.got_piece(i, a, b):
             for co in self.encoder.complete_connections:
                 co.send_have(i)
     elif t == PORT:
         if len(message) != 3:
             self.close()
             return
         self.dht_port = unpack('!H', message[1:3])[0]
         self.encoder.got_port(self)
     else:
         self.close()
Exemple #6
0
 def _got_message(self, message):
     t = message[0]
     if t == BITFIELD and self.got_anything:
         self.close()
         return
     self.got_anything = True
     if (t in [CHOKE, UNCHOKE, INTERESTED, NOT_INTERESTED]
             and len(message) != 1):
         self.close()
         return
     if t == CHOKE:
         self.download.got_choke()
     elif t == UNCHOKE:
         self.download.got_unchoke()
     elif t == INTERESTED:
         self.upload.got_interested()
     elif t == NOT_INTERESTED:
         self.upload.got_not_interested()
     elif t == HAVE:
         if len(message) != 5:
             self.close()
             return
         i = toint(message[1:])
         if i >= self.encoder.numpieces:
             self.close()
             return
         self.download.got_have(i)
     elif t == BITFIELD:
         try:
             b = Bitfield(self.encoder.numpieces, message[1:])
         except ValueError:
             self.close()
             return
         self.download.got_have_bitfield(b)
     elif t == REQUEST:
         if len(message) != 13:
             self.close()
             return
         i = toint(message[1:5])
         if i >= self.encoder.numpieces:
             self.close()
             return
         self.upload.got_request(i, toint(message[5:9]), toint(message[9:]))
     elif t == CANCEL:
         if len(message) != 13:
             self.close()
             return
         i = toint(message[1:5])
         if i >= self.encoder.numpieces:
             self.close()
             return
         self.upload.got_cancel(i, toint(message[5:9]), toint(message[9:]))
     elif t == PIECE:
         if len(message) <= 9:
             self.close()
             return
         i = toint(message[1:5])
         if i >= self.encoder.numpieces:
             self.close()
             return
         if self.download.got_piece(i, toint(message[5:9]), message[9:]):
             for co in self.encoder.complete_connections:
                 co.send_have(i)
     else:
         self.close()