class PeerClient(dict): """dictionary of all dowloads: {id(transport): }""" def __init__(self, peer, connect_method): dict.__init__(self) self.peer = peer self.connect = connect_method self.download_dlg = None # [ [split path], size] self.files = [] self.files_deferred = None def __setitem__(self, transport, download_msg): dict.__setitem__(self, id(transport), download_msg) def __getitem__(self, transport): try: return dict.__getitem__(self, id(transport)) except KeyError: raise SecurityAlert(transport.getPeer().host, _("Corrupted client")) # high level API # def auto_load(self): """download profile when meeting peer for the first time""" return self._connect(MESSAGE_HELLO) def get_profile(self): """download peer profile using self.get_file. Automatically called on client creation""" if self.peer.server.current_state == self.peer.server.new_state: SecurityAlert(self.peer.peer_id, "Can't get profile: peer's server not known yet") else: return self._connect(MESSAGE_PROFILE) def get_blog_file(self): """donload blog file using self.get_file""" if self.peer.server.current_state == self.peer.server.new_state: SecurityAlert(self.peer.peer_id, "Can't get blog: peer's server not known yet") else: return self._connect(MESSAGE_BLOG) def get_shared_files(self): """donload blog file using self.get_file""" if self.peer.server.current_state == self.peer.server.new_state: SecurityAlert(self.peer.peer_id, "Can't get list: peer's server not known yet") else: return self._connect(MESSAGE_SHARED) def get_files(self, file_descriptors): """download given list of file file_descriptor is a list: [ [split path], size ]""" if self.peer.server.current_state == self.peer.server.new_state: SecurityAlert(self.peer.peer_id, "Can't get files: peer's server not known yet") else: # display downlaod dialog if necessary if get_prefs("display_dl") \ and "wx" in sys.modules: print "xxx using wx" from solipsis.util.uiproxy import UIProxy from solipsis.services.profile.gui.DownloadDialog \ import DownloadDialog self.download_dlg = UIProxy(DownloadDialog( get_prefs("display_dl"), None, -1)) self.download_dlg.init() self.download_dlg.Show() # launch first download self.files = file_descriptors if self.files: split_path, size = self.files.pop() self.update_file(split_path[-1], size) self._connect(MESSAGE_FILES, format_data_file(split_path, size)) # create deferred to be called when all files downloaded deferred = defer.Deferred() self.files_deferred = deferred return self.files_deferred else: display_warning(_("Empty List"), _("No file selected to download")) # connection management # def _connect(self, command, data=None): # set download information message = self.peer.wrap_message(command, data) connector = self.connect(self.peer) deferred = defer.Deferred() download = DownloadMessage(connector.transport, deferred, message) self[connector.transport] = download # set callback if command == MESSAGE_HELLO: deferred.addCallback(self._on_hello) elif command == MESSAGE_PROFILE: deferred.addCallback(self._on_complete_profile) elif command == MESSAGE_BLOG: deferred.addCallback(self._on_complete_pickle) elif command == MESSAGE_SHARED: deferred.addCallback(self._on_complete_pickle) elif command == MESSAGE_FILES: deferred.addCallback(self._on_complete_file) else: raise ValueError("ERROR in _connect: %s not valid"% command) return deferred def rawDataReceived(self, transport, data): self[transport].write_data(data) self.update_download(self[transport].size) def _fail_client(self, transport, reason): display_warning("Action [%s] failed: %s"\ % (str(self[transport].message), reason)) self[transport].close(reason) def _on_connected(self, transport): self[transport].send_message() self[transport].setup_download() def _on_disconnected(self, transport, reason): self[transport].teardown_download() self[transport].close(reason) # callbacks # def _on_hello(self, donwload_msg): """callback when autoloading of profile successful""" document = read_document(donwload_msg.file) get_facade().set_data(self.peer.peer_id, document, flag_update=False) get_filter_facade().fill_data(self.peer.peer_id, document) def _on_complete_profile(self, donwload_msg): """callback when finished downloading profile""" return read_document(donwload_msg.file) def _on_complete_pickle(self, donwload_msg): """callback when finished downloading blog""" try: return pickle.load(donwload_msg.file) except Exception, err: display_error(_("Your version of Solipsis is not compatible " "with the peer'sone you wish to download from " "Make sure you both use the latest (%s)"\ % VERSION), title="Download error", error=err)