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)
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)
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()
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))
class DownloadPeer: 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) def _backlog(self, just_unchoked): # self.backlog = min( # 2+int(4*self.measure.get_rate()/self.downloader.chunksize), # (2*just_unchoked)+self.downloader.queue_limit() ) # if self.backlog > 50: # self.backlog = max(50, self.backlog * 0.075) # return self.backlog self.backlog = 4 + int( 8 * self.measure.get_rate() / self.downloader.chunksize) return self.backlog def disconnected(self): self.downloader.lost_peer(self) if self.have.complete(): self.downloader.picker.lost_seed() else: for i in xrange(len(self.have)): if self.have[i]: self.downloader.picker.lost_have(i) if self.have.complete() and self.downloader.storage.is_endgame(): self.downloader.add_disconnected_seed( self.connection.get_readable_id()) self._letgo() self.guard.download = None def _letgo(self): if self.downloader.queued_out.has_key(self): del self.downloader.queued_out[self] if not self.active_requests: return if self.downloader.endgamemode: self.active_requests = [] return lost = {} for index, begin, length in self.active_requests: self.downloader.storage.request_lost(index, begin, length) lost[index] = 1 lost = lost.keys() self.active_requests = [] if self.downloader.paused: return ds = [d for d in self.downloader.downloads if not d.choked] shuffle(ds) for d in ds: d._request_more() for d in self.downloader.downloads: if d.choked and not d.interested: for l in lost: if d.have[l] and self.downloader.storage.do_I_have_requests( l): d.send_interested() break def got_choke(self): if not self.choked: self.choked = True self._letgo() def got_unchoke(self): if self.choked: self.choked = False if self.interested: self._request_more(new_unchoke=True) self.last2 = clock() def is_choked(self): return self.choked def is_interested(self): return self.interested def send_interested(self): if not self.interested: self.interested = True self.connection.send_interested() if not self.choked: self.last2 = clock() def send_not_interested(self): if self.interested: self.interested = False self.connection.send_not_interested() def got_piece(self, index, begin, piece): length = len(piece) try: self.active_requests.remove((index, begin, length)) except ValueError: self.downloader.discarded += length return False if self.downloader.endgamemode: self.downloader.all_requests.remove((index, begin, length)) self.last = clock() self.last2 = clock() self.measure.update_rate(length) self.downloader.measurefunc(length) if not self.downloader.storage.piece_came_in(index, begin, piece, self.guard): self.downloader.piece_flunked(index) return False if self.downloader.storage.do_I_have(index): self.downloader.picker.complete(index) if self.downloader.endgamemode: for d in self.downloader.downloads: if d is not self: if d.interested: if d.choked: assert not d.active_requests d.fix_download_endgame() else: try: d.active_requests.remove( (index, begin, length)) except ValueError: continue d.connection.send_cancel(index, begin, length) d.fix_download_endgame() else: assert not d.active_requests self._request_more() self.downloader.check_complete(index) return self.downloader.storage.do_I_have(index) def _request_more(self, new_unchoke=False): assert not self.choked if self.downloader.endgamemode: self.fix_download_endgame(new_unchoke) return if self.downloader.paused: return if len(self.active_requests) >= self._backlog(new_unchoke): if not (self.active_requests or self.backlog): self.downloader.queued_out[self] = 1 return lost_interests = [] while len(self.active_requests) < self.backlog: interest = self.downloader.picker.next( self.have, self.downloader.storage.do_I_have_requests, self.downloader.too_many_partials()) if interest is None: break self.example_interest = interest self.send_interested() loop = True while len(self.active_requests) < self.backlog and loop: begin, length = self.downloader.storage.new_request(interest) self.downloader.picker.requested(interest) self.active_requests.append((interest, begin, length)) self.connection.send_request(interest, begin, length) self.downloader.chunk_requested(length) if not self.downloader.storage.do_I_have_requests(interest): loop = False lost_interests.append(interest) if not self.active_requests: self.send_not_interested() if lost_interests: for d in self.downloader.downloads: if d.active_requests or not d.interested: continue if d.example_interest is not None and self.downloader.storage.do_I_have_requests( d.example_interest): continue for lost in lost_interests: if d.have[lost]: break else: continue interest = self.downloader.picker.next( d.have, self.downloader.storage.do_I_have_requests, self.downloader.too_many_partials()) if interest is None: d.send_not_interested() else: d.example_interest = interest if self.downloader.storage.is_endgame(): self.downloader.start_endgame() def fix_download_endgame(self, new_unchoke=False): if self.downloader.paused: return if len(self.active_requests) >= self._backlog(new_unchoke): if not (self.active_requests or self.backlog) and not self.choked: self.downloader.queued_out[self] = 1 return want = [ a for a in self.downloader.all_requests if self.have[a[0]] and a not in self.active_requests ] if not (self.active_requests or want): self.send_not_interested() return if want: self.send_interested() if self.choked: return shuffle(want) del want[self.backlog - len(self.active_requests):] self.active_requests.extend(want) for piece, begin, length in want: self.connection.send_request(piece, begin, length) self.downloader.chunk_requested(length) def got_have(self, index): if index == self.downloader.numpieces - 1: self.downloader.totalmeasure.update_rate( self.downloader.storage.total_length - (self.downloader.numpieces - 1) * self.downloader.storage.piece_length) self.peermeasure.update_rate(self.downloader.storage.total_length - (self.downloader.numpieces - 1) * self.downloader.storage.piece_length) else: self.downloader.totalmeasure.update_rate( self.downloader.storage.piece_length) self.peermeasure.update_rate(self.downloader.storage.piece_length) if not self.have[index]: self.have[index] = True self.downloader.picker.got_have(index) if self.have.complete(): self.downloader.picker.became_seed() if self.downloader.storage.am_I_complete(): self.downloader.add_disconnected_seed( self.connection.get_readable_id()) self.connection.close() elif self.downloader.endgamemode: self.fix_download_endgame() elif (not self.downloader.paused and not self.downloader.picker.is_blocked(index) and self.downloader.storage.do_I_have_requests(index)): if not self.choked: self._request_more() else: self.send_interested() return self.have.complete() def _check_interests(self): if self.interested or self.downloader.paused: return for i in xrange(len(self.have)): if (self.have[i] and not self.downloader.picker.is_blocked(i) and (self.downloader.endgamemode or self.downloader.storage.do_I_have_requests(i))): self.send_interested() return def got_have_bitfield(self, have): if self.downloader.storage.am_I_complete() and have.complete(): if self.downloader.super_seeding: self.connection.send_bitfield( have.tostring()) # be nice, show you're a seed too self.connection.close() self.downloader.add_disconnected_seed( self.connection.get_readable_id()) return False self.have = have if have.complete(): self.downloader.picker.got_seed() else: temp = 4 for i in xrange(len(have)): if have[i]: self.downloader.picker.got_have(i) if self.downloader.endgamemode and not self.downloader.paused: for piece, begin, length in self.downloader.all_requests: if self.have[piece]: self.send_interested() break else: self._check_interests() return have.complete() def get_rate(self): return self.measure.get_rate() def get_peer_completion(self): if len(self.have) > 0: return float(len(self.have) - self.have.numfalse) / float( len(self.have)) else: return 1.0 def is_snubbed(self): if (self.interested and not self.choked and clock() - self.last2 > self.downloader.snub_time): for index, begin, length in self.active_requests: self.connection.send_cancel(index, begin, length) self.got_choke() # treat it just like a choke return clock() - self.last > self.downloader.snub_time
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()
class DownloadPeer: 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) def _backlog(self, just_unchoked): # self.backlog = min( # 2+int(4*self.measure.get_rate()/self.downloader.chunksize), # (2*just_unchoked)+self.downloader.queue_limit() ) # if self.backlog > 50: # self.backlog = max(50, self.backlog * 0.075) # return self.backlog self.backlog = 4+int(8*self.measure.get_rate()/self.downloader.chunksize) return self.backlog def disconnected(self): self.downloader.lost_peer(self) if self.have.complete(): self.downloader.picker.lost_seed() else: for i in xrange(len(self.have)): if self.have[i]: self.downloader.picker.lost_have(i) if self.have.complete() and self.downloader.storage.is_endgame(): self.downloader.add_disconnected_seed(self.connection.get_readable_id()) self._letgo() self.guard.download = None def _letgo(self): if self.downloader.queued_out.has_key(self): del self.downloader.queued_out[self] if not self.active_requests: return if self.downloader.endgamemode: self.active_requests = [] return lost = {} for index, begin, length in self.active_requests: self.downloader.storage.request_lost(index, begin, length) lost[index] = 1 lost = lost.keys() self.active_requests = [] if self.downloader.paused: return ds = [d for d in self.downloader.downloads if not d.choked] shuffle(ds) for d in ds: d._request_more() for d in self.downloader.downloads: if d.choked and not d.interested: for l in lost: if d.have[l] and self.downloader.storage.do_I_have_requests(l): d.send_interested() break def got_choke(self): if not self.choked: self.choked = True self._letgo() def got_unchoke(self): if self.choked: self.choked = False if self.interested: self._request_more(new_unchoke = True) self.last2 = clock() def is_choked(self): return self.choked def is_interested(self): return self.interested def send_interested(self): if not self.interested: self.interested = True self.connection.send_interested() if not self.choked: self.last2 = clock() def send_not_interested(self): if self.interested: self.interested = False self.connection.send_not_interested() def got_piece(self, index, begin, piece): length = len(piece) try: self.active_requests.remove((index, begin, length)) except ValueError: self.downloader.discarded += length return False if self.downloader.endgamemode: self.downloader.all_requests.remove((index, begin, length)) self.last = clock() self.last2 = clock() self.measure.update_rate(length) self.downloader.measurefunc(length) if not self.downloader.storage.piece_came_in(index, begin, piece, self.guard): self.downloader.piece_flunked(index) return False if self.downloader.storage.do_I_have(index): self.downloader.picker.complete(index) if self.downloader.endgamemode: for d in self.downloader.downloads: if d is not self: if d.interested: if d.choked: assert not d.active_requests d.fix_download_endgame() else: try: d.active_requests.remove((index, begin, length)) except ValueError: continue d.connection.send_cancel(index, begin, length) d.fix_download_endgame() else: assert not d.active_requests self._request_more() self.downloader.check_complete(index) return self.downloader.storage.do_I_have(index) def _request_more(self, new_unchoke = False): assert not self.choked if self.downloader.endgamemode: self.fix_download_endgame(new_unchoke) return if self.downloader.paused: return if len(self.active_requests) >= self._backlog(new_unchoke): if not (self.active_requests or self.backlog): self.downloader.queued_out[self] = 1 return lost_interests = [] while len(self.active_requests) < self.backlog: interest = self.downloader.picker.next(self.have, self.downloader.storage.do_I_have_requests, self.downloader.too_many_partials()) if interest is None: break self.example_interest = interest self.send_interested() loop = True while len(self.active_requests) < self.backlog and loop: begin, length = self.downloader.storage.new_request(interest) self.downloader.picker.requested(interest) self.active_requests.append((interest, begin, length)) self.connection.send_request(interest, begin, length) self.downloader.chunk_requested(length) if not self.downloader.storage.do_I_have_requests(interest): loop = False lost_interests.append(interest) if not self.active_requests: self.send_not_interested() if lost_interests: for d in self.downloader.downloads: if d.active_requests or not d.interested: continue if d.example_interest is not None and self.downloader.storage.do_I_have_requests(d.example_interest): continue for lost in lost_interests: if d.have[lost]: break else: continue interest = self.downloader.picker.next(d.have, self.downloader.storage.do_I_have_requests, self.downloader.too_many_partials()) if interest is None: d.send_not_interested() else: d.example_interest = interest if self.downloader.storage.is_endgame(): self.downloader.start_endgame() def fix_download_endgame(self, new_unchoke = False): if self.downloader.paused: return if len(self.active_requests) >= self._backlog(new_unchoke): if not (self.active_requests or self.backlog) and not self.choked: self.downloader.queued_out[self] = 1 return want = [a for a in self.downloader.all_requests if self.have[a[0]] and a not in self.active_requests] if not (self.active_requests or want): self.send_not_interested() return if want: self.send_interested() if self.choked: return shuffle(want) del want[self.backlog - len(self.active_requests):] self.active_requests.extend(want) for piece, begin, length in want: self.connection.send_request(piece, begin, length) self.downloader.chunk_requested(length) def got_have(self, index): if index == self.downloader.numpieces-1: self.downloader.totalmeasure.update_rate(self.downloader.storage.total_length-(self.downloader.numpieces-1)*self.downloader.storage.piece_length) self.peermeasure.update_rate(self.downloader.storage.total_length-(self.downloader.numpieces-1)*self.downloader.storage.piece_length) else: self.downloader.totalmeasure.update_rate(self.downloader.storage.piece_length) self.peermeasure.update_rate(self.downloader.storage.piece_length) if not self.have[index]: self.have[index] = True self.downloader.picker.got_have(index) if self.have.complete(): self.downloader.picker.became_seed() if self.downloader.storage.am_I_complete(): self.downloader.add_disconnected_seed(self.connection.get_readable_id()) self.connection.close() elif self.downloader.endgamemode: self.fix_download_endgame() elif ( not self.downloader.paused and not self.downloader.picker.is_blocked(index) and self.downloader.storage.do_I_have_requests(index) ): if not self.choked: self._request_more() else: self.send_interested() return self.have.complete() def _check_interests(self): if self.interested or self.downloader.paused: return for i in xrange(len(self.have)): if ( self.have[i] and not self.downloader.picker.is_blocked(i) and ( self.downloader.endgamemode or self.downloader.storage.do_I_have_requests(i) ) ): self.send_interested() return def got_have_bitfield(self, have): if self.downloader.storage.am_I_complete() and have.complete(): if self.downloader.super_seeding: self.connection.send_bitfield(have.tostring()) # be nice, show you're a seed too self.connection.close() self.downloader.add_disconnected_seed(self.connection.get_readable_id()) return False self.have = have if have.complete(): self.downloader.picker.got_seed() else: temp = 4 for i in xrange(len(have)): if have[i]: self.downloader.picker.got_have(i) if self.downloader.endgamemode and not self.downloader.paused: for piece, begin, length in self.downloader.all_requests: if self.have[piece]: self.send_interested() break else: self._check_interests() return have.complete() def get_rate(self): return self.measure.get_rate() def get_peer_completion(self): if len(self.have) > 0: return float(len(self.have)-self.have.numfalse)/float(len(self.have)) else: return 1.0 def is_snubbed(self): if ( self.interested and not self.choked and clock() - self.last2 > self.downloader.snub_time ): for index, begin, length in self.active_requests: self.connection.send_cancel(index, begin, length) self.got_choke() # treat it just like a choke return clock() - self.last > self.downloader.snub_time
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()