def _leader_lookup(self, data): # TODO: there is absolutely no use of sending uuid of the message initiator # uuid, text_search = data text_search = data['search_query'] filtered_response = [] for uuid in self.factory.data_from_peers.keys(): for filename in self.factory.data_from_peers[uuid]['filenames']: if fuzz.partial_ratio(text_search.lower(), filename.lower()) >= 55: file_hash = self.factory.data_from_peers[uuid][ 'filenames'][filename] try: filtered_response.append( self.factory.data_from_peers[uuid]['hashes'] [file_hash]) except Exception as e: print e print_log('BIGGEST MESS UP {0}'.format(filename), WARNING_LOG) if len(self.factory.data_from_peers.keys()) == 0: filtered_response = [] # update_msg = Basemessage(key=SEARCH_RES, data=filtered_response) update_msg = bake(SEARCH_RES, search_query_response=filtered_response) self.sendLine(update_msg) # this we are sending it back to the server # leader will loseConnection with the requesting server self.transport.loseConnection()
def _remove_dead_entry(self, data): uuid = data['dead_uuid'] print_log('removing entry {0}'.format(uuid)) try: del self.factory.data_from_peers[uuid] except: raise ServerException( 1, '{0} not available in cached data'.format(uuid))
def _update_leader(self, data): self.factory.leader = data['leader'] print_log('Updating Leader {0}'.format(self.factory.book.leader)) if self.factory.state == READY and self.leaderThere( ) and self.factory.shared_folder is not None: file_meta_data = yield fileHashUtils.bootstrap( self.factory.shared_folder, self.factory.dbpool) self.fileindexing_complete(file_meta_data)
def display_error(self, data): ''' callback: displays leader/tracker not available triggered when leader not ready ''' # print 'Tracker not available..' print_log(data['reason'], WARNING_LOG) reactor.stop()
def _handshake(self, data): filehash = data['filehash'] if self.factory.state == READY: piece_hashes = yield fileHashUtils.get_piecehashes_of( filehash, self.factory.dbpool) ack_msg = bake(FILE_CONFIRMATION_MESSAGE, piecehashes=piece_hashes) self.sendLine(ack_msg) else: print_log('not ready yet', WARNING_LOG)
def clientConnectionFailed(self, connector, reason): try: if self.query == SHARE: update_config(shared_folder=self.arguments) elif self.query == CHANGE: update_config(download_folder=self.arguments) else: print_log('iwant server is not running', ERROR_LOG) finally: reactor.stop()
def fileindexing_complete(self, indexing_response): # print_log('Files completely indexed') # print_log('SHARING {0}'.format(indexing_response['shared_folder'])) for file_name in indexing_response['ADD']: print_log('[Adding] {0} \t {1}'.format(file_name[0], file_name[1])) for file_name in indexing_response['DEL']: print_log('[Removing] {0}'.format(file_name[0])) self.factory.state = READY del indexing_response['shared_folder'] if self.leaderThere(): self.factory._notify_leader(HASH_DUMP, indexing_response)
def _leader_send_list(self, data): if self.leaderThere(): print_log('lookup request sent to leader') search_query = data['search_query'] self.factory._notify_leader(key=LOOKUP, data=search_query, persist=True, clientConn=self) else: # msg = Basemessage(key=LEADER_NOT_READY, data=None) msg = bake(key=LEADER_NOT_READY, reason='Tracker is not available') self.sendLine(msg) self.transport.loseConnection()
def _change_download_folder(self, data): new_download_folder = data['download_folder'] msg = bake(NEW_DOWNLOAD_FOLDER_RES, download_folder_response=new_download_folder) if not os.path.isdir(new_download_folder): msg = bake( NEW_DOWNLOAD_FOLDER_RES, download_folder_response='Invalid download path provided') else: print_log( 'changed download folder to {0}'.format(new_download_folder)) self.factory.download_folder = new_download_folder self.sendLine(msg) self.transport.loseConnection()
def _load_file(self, data): fhash = data['filehash'] if self.factory.state == READY: self.fileObj = yield fileHashUtils.get_file( fhash, self.factory.dbpool) self.chunk_size = piece_size( fileHashUtils.get_file_size(self.fileObj.name)) # unchoke_msg = Basemessage(key=UNCHOKE, data=None) unchoke_msg = bake(key=UNCHOKE, unchoke=True) self.sendLine(unchoke_msg) else: print_log( 'need to handle this part where files are not indexed yet', ERROR_LOG)
def _ask_leader_for_peers(self, data): if self.leaderThere(): print_log('asking leaders for peers') #print_log( data) filehash = data['filehash'] self.factory._notify_leader(key=SEND_PEER_DETAILS, data=filehash, persist=True, clientConn=self) else: # msg = Basemessage(key=LEADER_NOT_READY, data=None) msg = bake(key=LEADER_NOT_READY, reason='Tracker is not available') self.sendLine(msg) self.transport.loseConnection()
def show_search_results(self, data): ''' callback: displays file search response from the leader(via local server) triggered when server replies the file search response from the leader to the client ''' search_response = data['search_query_response'] response = [] for i in search_response: response.append(i[:-1]) print_log( tabulate.tabulate( response, headers=["Filename", "Size", "Checksum", "RootHash"]), CLIENT_LOG_INFO) reactor.stop()
def _dump_data_from_peers(self, data): uuid = data['identity'] file_addition_updates = data['operation']['ADD'] file_removal_updates = data['operation']['DEL'] for file_properties in file_addition_updates: pass # print_log( # '[Leader Adding] {0} \t {1}'.format( # file_properties[0], # file_properties[1])) for file_properties in file_removal_updates: print_log('[Leader Removing] {0}'.format(file_properties[0])) if uuid not in self.factory.data_from_peers.keys(): self.factory.data_from_peers[uuid] = {} self.factory.data_from_peers[uuid]['hashes'] = {} self.factory.data_from_peers[uuid]['filenames'] = {} for fproperty in file_addition_updates: file_hash = fproperty[2] file_name = fproperty[0] if file_name in self.factory.data_from_peers[uuid]['filenames']: old_hash_key = self.factory.data_from_peers[uuid]['filenames'][ file_name] try: del self.factory.data_from_peers[uuid]['hashes'][ old_hash_key] except Exception as e: print_log( 'need to handle this major issue : {0}, for reason {1}' .format(file_name, e), WARNING_LOG) if file_hash not in self.factory.data_from_peers[uuid]: self.factory.data_from_peers[uuid]['hashes'][ file_hash] = fproperty self.factory.data_from_peers[uuid]['filenames'][ file_name] = file_hash for fproperty in file_removal_updates: file_name = fproperty[0] file_hash = fproperty[2] if file_hash in self.factory.data_from_peers[uuid]['hashes']: del self.factory.data_from_peers[uuid]['hashes'][file_hash] del self.factory.data_from_peers[uuid]['filenames'][file_name] print_log('deleting hash : {0} filename {1}'.format( file_hash, file_name)) else: if file_name in self.factory.data_from_peers[uuid][ 'filenames']: # very very stupid hack [ just because of empty files ] del self.factory.data_from_peers[uuid]['filenames'][ file_name] print_log('deleting HACK : {0} filename {1}'.format( file_hash, file_name))
def talk_to_peer(self, data): from twisted.internet import reactor self.transport.loseConnection() if len(data) == 0: print_log( 'Tell the client that peer lookup response is 0. Have to handle this', WARNING_LOG) # update_msg = Basemessage(key=SEARCH_RES, data=data) else: from iwant.core.protocols import DownloadManagerFactory response = data['peer_lookup_response'] file_root_hash = response['file_root_hash'] peers = map(lambda host: host[0], response['peers']) checksum = self.factory.dump reactor.connectTCP( peers[0], SERVER_DAEMON_PORT, DownloadManagerFactory(clientConn, self.factory.download_folder, checksum, file_root_hash, peers, self.factory.dbpool))
def show_file_to_be_downloaded(self, data): ''' callback: displays file to be downloaded triggered when user downloads a file ''' file_structure_response = data['message'] if file_structure_response['isFile']: file_name = file_structure_response['filename'] file_size = file_structure_response['filesize'] checksum = file_structure_response['checksum'] print_log( 'Filename: {0}\nSize: {1} MB'.format(file_name, file_size), CLIENT_LOG_INFO) else: root_directory = file_structure_response['rootDirectory'] root_directory_checksum = file_structure_response[ 'rootDirectoryChecksum'] print_log( 'Directory: {0}\nDirectory Checksum: {1}'.format( root_directory, root_directory_checksum), CLIENT_LOG_INFO) files = file_structure_response['files'] for file_property in files: filename, size, checksum = file_property print_log('Filename: {0}\tSize: {1} MB'.format(filename, size), CLIENT_LOG_INFO) reactor.stop()
def _end_game(self, data): if data['end_game']: print_log('received end game') self.fileObj.close()
def confirm_new_download_folder(self, data): print_log( 'Download Folder: {0}'.format(data['download_folder_response']), CLIENT_LOG_INFO) reactor.stop()
def confirm_new_shared_folder(self, data): print_log('Shared Folder: {0}'.format(data['shared_folder_response']), CLIENT_LOG_INFO) reactor.stop()
def _notify_leader(self, key=None, data=None, persist=False, clientConn=None): from twisted.internet.protocol import ClientFactory from twisted.internet import reactor class ServerLeaderProtocol(BaseProtocol): def __init__(self, factory): self.buff = '' self.delimiter = '\r' self.special_handler = None self.factory = factory self.events = { PEER_LOOKUP_RESPONSE: self.talk_to_peer, SEARCH_RES: self.send_file_search_response, HASH_NOT_PRESENT: self.invalid_file_response } def connectionMade(self): if self.factory.key == LOOKUP: update_msg = bake(LOOKUP, search_query=self.factory.dump) elif self.factory.key == HASH_DUMP: update_msg = bake(HASH_DUMP, identity=self.factory.identity, operation=self.factory.dump) elif self.factory.key == SEND_PEER_DETAILS: update_msg = bake(SEND_PEER_DETAILS, filehash=self.factory.dump) # self.transport.write(str(update_msg)) self.sendLine(update_msg) if not persist: self.transport.loseConnection() def serviceMessage(self, data): key, value = unbake(message=data) self.events[key](value) def invalid_file_response(self, data): reason = data['reason'] msg = bake(HASH_NOT_PRESENT, reason=reason) clientConn.sendLine(msg) clientConn.transport.loseConnection() def talk_to_peer(self, data): from twisted.internet import reactor self.transport.loseConnection() if len(data) == 0: print_log( 'Tell the client that peer lookup response is 0. Have to handle this', WARNING_LOG) # update_msg = Basemessage(key=SEARCH_RES, data=data) else: from iwant.core.protocols import DownloadManagerFactory response = data['peer_lookup_response'] file_root_hash = response['file_root_hash'] peers = map(lambda host: host[0], response['peers']) checksum = self.factory.dump reactor.connectTCP( peers[0], SERVER_DAEMON_PORT, DownloadManagerFactory(clientConn, self.factory.download_folder, checksum, file_root_hash, peers, self.factory.dbpool)) def send_file_search_response(self, data): update_msg = bake( SEARCH_RES, search_query_response=data['search_query_response']) clientConn.sendLine(update_msg) clientConn.transport.loseConnection() class ServerLeaderFactory(ClientFactory): def __init__(self, key, dump, **kwargs): self.key = key self.dump = dump self.download_folder = kwargs['download_folder'] self.dbpool = kwargs['dbpool'] self.identity = kwargs['identity'] def clientConnectionLost(self, connector, reason): # print 'connection with leader dropped' pass def clientConnectionFailed(self, connector, reason): # print 'connection with leader dropped' pass def buildProtocol(self, addr): return ServerLeaderProtocol(self) if key == HASH_DUMP: factory = ServerLeaderFactory(key=key, dump=data, identity=self.book.uuidObj, dbpool=None, download_folder=None) elif key == LOOKUP: factory = ServerLeaderFactory(key=key, dump=data, identity=None, dbpool=None, download_folder=None) elif key == SEND_PEER_DETAILS: factory = ServerLeaderFactory(key=key, dump=data, identity=None, download_folder=self.download_folder, dbpool=self.dbpool) if key == SEND_PEER_DETAILS or key == LOOKUP: if self.leader is not None: host, port = self.leader[0], self.leader[1] print_log('connecting to {0}:{1} for {2}'.format( host, port, key)) reactor.connectTCP(host, port, factory) elif key == HASH_DUMP: if self.leader is not None and self.state == READY: host, port = self.leader[0], self.leader[1] print_log('connecting to {0}:{1} for {2}'.format( host, port, key)) reactor.connectTCP(host, port, factory)