def deal_with_message(self, data): messages_to_send_list = [] if self.message_buffer: self.message_buffer.extend(bytearray(data)) else: self.message_buffer = bytearray(data) if self.message_buffer[1:20].lower() == "bittorrent protocol": print "Handshake Received!" self.decode_handshake( self.factory.active_torrent.torrent_info) #compare info-hash self.message_buffer = self.message_buffer[68:] messages_to_send_list.append(messages.Interested( )) #we send interested when we receive handhake self.interested = True if len(self.message_buffer) >= 4: message_length = messages.bytes_to_number( self.message_buffer[0:4]) + 4 while len(self.message_buffer) >= message_length: messages_to_send_list = self.parse_messages( messages_to_send_list) message_length = messages.bytes_to_number( self.message_buffer[0:4]) + 4 #print messages_to_send_list[0] return messages_to_send_list
def recv_handshake(self): """Receives and processes peer's handshake reply""" print "<----- Receiving handshake reply from ", self.id re_handshake = self.socket.recv(68) if len(re_handshake) > 68 or len(re_handshake) < 68: print "Expected handshake but received something else: ", re_handshake else: reh_unpacked = unpack("!B19s8x20s20s", re_handshake) self.handshake = True self.interested = True interested = messages.Interested() self.send_next_message(interested.assemble())
def parse_message_from_response(self): length = messages.bytes_to_number( self.message_buffer[0:4] ) + 4 #length indicated by the first 4 bytes + 4 for those first 4 bytes bytestring = self.message_buffer[:length] if self.message_buffer[0:4] == '\x00\x00\x00\x00': #no msg_id message_obj = KeepAlive(response=bytestring) else: message_obj = { 0: lambda: messages.Choke(response=bytestring), 1: lambda: messages.Unchoke(response=bytestring), 2: lambda: messages.Interested(response=bytestring), 3: lambda: messaged.Interested(response=bytestring), 4: lambda: messages.Have(response=bytestring), 5: lambda: messages.Bitfield(response=bytestring), 6: lambda: messages.Request(response=bytestring), 7: lambda: messages.Piece(response=bytestring), 8: lambda: messages.Cancel(response=bytestring), 9: lambda: messages.Port(response=bytestring), }[self.message_buffer[4]]() #response[4] is the msg_id self.message_buffer = self.message_buffer[length:] return message_obj
def send_interested(self): interested = messages.Interested().encode() #print("\033[93mSending Interested Message to Peer IP: {}, Port: {}\033[0m".format(self.ip, self.port)) self.changeStatus("\033[93mSending Interested Message to Peer\033[0m") self.send_msg(interested) self.state['am_interested'] = True
def react_to_message(self, message_id, payload): mlist = { "keepalive": None, "choke": 0, "unchoke": 1, "interested": 2, "not interested": 3, "have": 4, "bitfield": 5, "request": 6, "piece": 7, "cancel": 8, "port": 9 } if message_id == mlist["keepalive"]: pass if message_id == mlist["choke"]: print "<----- Got 'Choke' message from peer ", self.id self.choked = True if message_id == mlist["unchoke"]: # Unchoke received, ready to send request print "====================== Got 'Unchoke' message from peer %r ======================" % self.id self.choked = False if message_id == mlist["interested"]: print "<----- Got 'Interested' message from peer ", self.id if message_id == mlist["not interested"]: print "<----- Got 'Not Interested' message from peer ", self.id self.interested = False if message_id == mlist["have"]: print "====================== Got 'Have' message from peer %r advertising piece of index %r ======================" % ( self.id, (unpack("!I", payload))[0]) self.bitfield.update_bitfield((unpack("!I", payload))[0]) self.interested = True interested = messages.Interested() self.send_next_message(interested.assemble()) print "Sending 'Interested' message to peer %r..." % self.id if message_id == mlist["bitfield"]: print "====================== Got 'Bitfield' message from peer %r ======================" % self.id self.bitfield.set_bitfield_from_payload(payload) bitfield_message = messages.BitMessage() self.send_next_message(bitfield_message.assemble(self.torrent)) print "Sending 'Bitfield' message to peer %r..." % self.id if message_id == mlist["piece"]: self.downloading = True piece_index = unpack("!I", payload[0:4])[0] piece_begin = unpack("!I", payload[4:8])[0] self.piece_data += payload[8:] if piece_index != self.last_piece_index: self.check_piece_completeness(piece_index) else: self.process_last_piece(piece_index) if message_id == mlist["cancel"]: print "<----- Got 'Cancel' message!" if message_id == mlist["port"]: print "<----- Got 'Port' message!" if message_id == mlist["request"]: print "<----- Got 'Request' message!"
def react_to_message(self, message_id, payload): """Process messages and respond accordingly""" mlist = {"keepalive":None, "choke": 0, "unchoke": 1, "interested":2, "not interested": 3, "have": 4, "bitfield": 5, "request": 6, "piece":7, "cancel": 8, "port": 9} if message_id == mlist["keepalive"]: # Keepalive - so ignore pass if message_id == mlist["choke"]: # Choke received, what to do? Send keepalives as usual and wait for unchoke print "<----- Got 'Choke' message from peer ", self.id self.choked = True if message_id == mlist["unchoke"]: # Unchoke received, ready to send request print "====================== Got 'Unchoke' message from peer %r ======================" %self.id self.choked = False if message_id == mlist["interested"]: print "<----- Got 'Interested' message from peer ", self.id # Interested received, handle this later because it's for seeding if message_id == mlist["not interested"]: print "<----- Got 'Not Interested' message from peer ", self.id # If you sent the bitfield and the peer doesn't have the pieces you need - so drop the connection self.interested = False if message_id == mlist["have"]: print "====================== Got 'Have' message from peer %r advertising piece of index %r ======================" %(self.id, (unpack("!I", payload))[0]) # Update bitfield for this peer with advertised piece self.bitfield.update_bitfield((unpack("!I", payload))[0]) # Send Interested message back self.interested = True interested = messages.Interested() self.send_next_message(interested.assemble()) print "Sending 'Interested' message to peer %r..." %self.id if message_id == mlist["bitfield"]: print "====================== Got 'Bitfield' message from peer %r ======================" % self.id self.bitfield.set_bitfield_from_payload(payload) # Send your own Bitfield and Interested bitfield_message = messages.BitMessage() self.send_next_message(bitfield_message.assemble(self.torrent)) print "Sending 'Bitfield' message to peer %r..." %self.id if message_id == mlist["piece"]: self.downloading = True # print "----------------------------------------------------------------Received subpiece" piece_index = unpack("!I", payload[0:4])[0] piece_begin = unpack("!I", payload[4:8])[0] self.piece_data += payload[8:] # print "Piece index: ", piece_index # print "Piece begin: ", piece_begin if piece_index != self.last_piece_index: self.check_piece_completeness(piece_index) else: self.process_last_piece(piece_index) if message_id == mlist["cancel"]: print "<----- Got 'Cancel' message!" if message_id == mlist["port"]: print "<----- Got 'Port' message!" if message_id == mlist["request"]: print "<----- Got 'Request' message!"