def __init__(self, reactor, peer_id, port, raw_data = None, torrent_dict = None): super(Torrent, self).__init__() if(raw_data == None and torrent_dict == None): Logger.error("Not Enough Information to get Torrent Data.\nCannot Ignore Error. Program will now Terminate") elif (torrent_dict == None and raw_data != None): torrent_dict = Bencoder.bdecode(raw_data) self.started = False self.reactor = reactor self.start_time = time.time() self.comment = torrent_dict['comment'] self.info = torrent_dict['info'] self.announce_list = torrent_dict['announce-list'] self.announce = torrent_dict['announce'] self.peer_id = peer_id self.port = port self.payload = self.generateBasicPayload() self.protocol = Core.BitTorrentFactory(self) self.fileManager = FileManager.FileManager(self.info) self.requester = RequestManager.RequestManager(self) self.payload = self.updatePayload() # The handhshake message to be sent is constant for a given torrent # str() has been overloaded self.handshake_message = str(Messages.Handshake(self.payload['info_hash'], self.payload['peer_id'])) print "Total number of pieces :", len(self.info['pieces'])
def decode_msg(self): """ Read and remove a message from the beginning of the buffer. :return: an instance of the message object """ if len(self.buffer) < 4: print('no message received') return None if self.buffer[:20] == struct.pack('>b19s', 19, b'BitTorrent protocol'): raw_handshake = self.buffer[:68] # handshakes should be 68 bytes offset = 20 # first 20 bytes are pstr and pstrlen which don't really matter now info_hash, peer_id = struct.unpack_from('>8x20s20s', raw_handshake, offset) handshake = Messages.Handshake(info_hash, peer_id) self.buffer = self.buffer[68:] # remove handshake from buffer return handshake try: msg_len, msg_id = struct.unpack('>Ib', self.buffer[:5]) total_len = msg_len + 4 if total_len > len(self.buffer): print('full message not received') return None raw_msg = self.buffer[:total_len] self.buffer = self.buffer[total_len:] # remove msg from buffer try: msg = Messages.map_id_to_obj[msg_id].decode(raw_msg) print('Peer.decode_msg(): decoded message: ') print(msg) return msg except KeyError as e: print(e) except struct.error as e: print(f'error in decode_msg(): {e}') return None
def parseHandshake(self, data=""): # If the Info Hash matches the torrent's info hash, add the peer to the successful handshake set handshake_response_data = Messages.Handshake(data) handshake_info_hash = handshake_response_data.info_hash if handshake_info_hash == urllib.unquote( self.torrent.payload['info_hash']): self.factory.peers_handshaken.add((self.ip, self.port)) # Check if Should we be interested or not else choke the peer if not already choked and add a timeout self.transport.write(str(Messages.Interested())) self.buffer += data[68:] self.transport.write( str( Messages.Bitfield(bitfield=self.torrent.fileManager. pieces_status.tobytes()))) else: self.killPeer() return
def send_handshake(self): """ Send handshake to the peer. """ handshake = Messages.Handshake(self.torrent.info_hash, self.peer_id) self.send_msg(handshake.encode())