diff --git a/electrum b/electrum index d123faea8..91141eeed 100755 --- a/electrum +++ b/electrum @@ -130,13 +130,11 @@ if __name__ == '__main__': # network interface network = Network(config) network.start() - #interface.send([('server.peers.subscribe',[])]) gui = gui.ElectrumGui(config, network) gui.main(url) network.stop() - # we use daemon threads, their termination is enforced. # this sleep command gives them time to terminate cleanly. time.sleep(0.1) @@ -319,15 +317,13 @@ if __name__ == '__main__': # open session if cmd not in offline_commands and not options.offline: - interface = Interface(config) - interface.register_callback('connected', lambda: sys.stderr.write("Connected to " + interface.connection_msg + "\n")) - - if not interface.start(wait=True): + network = Network(config) + network.register_callback('connected', lambda: sys.stderr.write("Connected to " + network.interface.connection_msg + "\n")) + if not network.start(wait=True): print_msg("Not connected, aborting.") sys.exit(1) - blockchain = BlockchainVerifier(interface, config) - blockchain.start() - wallet.start_threads(interface, blockchain) + + wallet.start_threads(network) wallet.update() @@ -388,7 +384,6 @@ if __name__ == '__main__': if cmd not in offline_commands and not options.offline: wallet.stop_threads() - interface.stop() - blockchain.stop() + network.stop() time.sleep(0.1) sys.exit(0) diff --git a/gui/gui_classic.py b/gui/gui_classic.py index cec3f1481..53ce98f97 100644 --- a/gui/gui_classic.py +++ b/gui/gui_classic.py @@ -227,10 +227,11 @@ class ElectrumWindow(QMainWindow): self.showNormal() - def __init__(self, config): + def __init__(self, config, network): QMainWindow.__init__(self) self.config = config + self.network = network self.init_plugins() self._close_electrum = False @@ -303,11 +304,11 @@ class ElectrumWindow(QMainWindow): import electrum self.wallet = wallet - self.wallet.interface.register_callback('updated', lambda: self.need_update.set()) - self.wallet.interface.register_callback('banner', lambda: self.emit(QtCore.SIGNAL('banner_signal'))) - self.wallet.interface.register_callback('disconnected', lambda: self.emit(QtCore.SIGNAL('update_status'))) - self.wallet.interface.register_callback('disconnecting', lambda: self.emit(QtCore.SIGNAL('update_status'))) - self.wallet.interface.register_callback('new_transaction', lambda: self.emit(QtCore.SIGNAL('transaction_signal'))) + self.network.register_callback('updated', lambda: self.need_update.set()) + self.network.register_callback('banner', lambda: self.emit(QtCore.SIGNAL('banner_signal'))) + self.network.register_callback('disconnected', lambda: self.emit(QtCore.SIGNAL('update_status'))) + self.network.register_callback('disconnecting', lambda: self.emit(QtCore.SIGNAL('update_status'))) + self.network.register_callback('new_transaction', lambda: self.emit(QtCore.SIGNAL('transaction_signal'))) title = 'Electrum ' + self.wallet.electrum_version + ' - ' + self.wallet.storage.path if not self.wallet.seed: title += ' [%s]' % (_('seedless')) self.setWindowTitle( title ) @@ -2283,7 +2284,7 @@ class ElectrumGui: s = Timer() s.start() - w = ElectrumWindow(self.config) + w = ElectrumWindow(self.config, self.network) w.load_wallet(wallet) self.windows.append(w) diff --git a/lib/blockchain.py b/lib/blockchain.py index 6f495ac40..e16d91659 100644 --- a/lib/blockchain.py +++ b/lib/blockchain.py @@ -56,17 +56,19 @@ class Blockchain(threading.Thread): while self.is_running(): try: - i, result = self.queue.get() + result = self.queue.get() except Queue.Empty: continue + if not result: continue + + i, result = result header= result.get('result') - #print_error( i.server, header ) height = header.get('block_height') if height > self.local_height + 50: self.get_chunks(i, header, height) - i.trigger_callback('updated') + i.network.trigger_callback('updated') if height > self.local_height: # get missing parts from interface (until it connects to my chain) @@ -85,7 +87,7 @@ class Blockchain(threading.Thread): print_error("error", i.server) # todo: dismiss that server - i.trigger_callback('updated') + i.network.trigger_callback('updated') diff --git a/lib/interface.py b/lib/interface.py index faf165ccf..770a65458 100644 --- a/lib/interface.py +++ b/lib/interface.py @@ -67,19 +67,6 @@ def pick_random_server(): class Interface(threading.Thread): - def register_callback(self, event, callback): - with self.lock: - if not self.callbacks.get(event): - self.callbacks[event] = [] - self.callbacks[event].append(callback) - - - def trigger_callback(self, event): - with self.lock: - callbacks = self.callbacks.get(event,[])[:] - if callbacks: - [callback() for callback in callbacks] - def init_server(self, host, port, proxy=None, use_ssl=True): self.host = host @@ -156,11 +143,11 @@ class Interface(threading.Thread): elif method == 'server.banner': self.banner = result - self.trigger_callback('banner') + self.network.trigger_callback('banner') elif method == 'server.peers.subscribe': self.servers = self.parse_servers(result) - self.trigger_callback('peers') + self.network.trigger_callback('peers') else: # notification: find the channel(s) @@ -196,8 +183,9 @@ class Interface(threading.Thread): def get_response(self, channel='default', block=True, timeout=10000000000): - i, r = self.responses[channel].get(block, timeout) - return r + ir = self.responses[channel].get(block, timeout) + if ir: + return ir[1] def register_channel(self, channel, queue=None): if queue is None: @@ -441,7 +429,6 @@ class Interface(threading.Thread): self.responses = {} self.responses['default'] = Queue.Queue() - self.callbacks = {} self.lock = threading.Lock() self.servers = {} # actual list from IRC diff --git a/lib/network.py b/lib/network.py index 9f293176c..657d6f8ac 100644 --- a/lib/network.py +++ b/lib/network.py @@ -17,8 +17,22 @@ class Network(threading.Thread): self.queue = Queue.Queue() self.default_server = self.config.get('server') self.servers_list = interface.filter_protocol(interface.DEFAULT_SERVERS,'s') + self.callbacks = {} + def register_callback(self, event, callback): + with self.lock: + if not self.callbacks.get(event): + self.callbacks[event] = [] + self.callbacks[event].append(callback) + + + def trigger_callback(self, event): + with self.lock: + callbacks = self.callbacks.get(event,[])[:] + if callbacks: + [callback() for callback in callbacks] + def start_interfaces(self): @@ -26,22 +40,29 @@ class Network(threading.Thread): self.interfaces[server] = interface.Interface({'server':server}) for i in self.interfaces.values(): + i.network = self # fixme i.start(self.queue) if self.default_server: self.interface = interface.Interface({'server':self.default_server}) + self.interface.network = self # fixme self.interface.start(self.queue) else: self.interface = self.interfaces[0] + def start(self, wait=False): + self.start_interfaces() + threading.Thread.__init__(self) + if wait: + self.interface.connect_event.wait() + return self.interface.is_connected def run(self): self.blockchain.start() - self.start_interfaces() with self.lock: self.running = True diff --git a/lib/verifier.py b/lib/verifier.py index 4cacfc20b..097dd9844 100644 --- a/lib/verifier.py +++ b/lib/verifier.py @@ -90,7 +90,7 @@ class TxVerifier(threading.Thread): def stop(self): with self.lock: self.running = False - self.interface.poke('verifier') + #self.interface.poke('verifier') def is_running(self): with self.lock: return self.running diff --git a/lib/wallet.py b/lib/wallet.py index adacd3adc..7a98afc0b 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -1447,7 +1447,7 @@ class WalletSynchronizer(threading.Thread): self.was_updated = True if self.was_updated: - self.interface.trigger_callback('updated') + self.interface.network.trigger_callback('updated') self.was_updated = False # 2. get a response @@ -1523,8 +1523,7 @@ class WalletSynchronizer(threading.Thread): print_error("Error: Unknown message:" + method + ", " + repr(params) + ", " + repr(result) ) if self.was_updated and not requested_tx: - self.interface.trigger_callback('updated') - self.interface.trigger_callback("new_transaction") # Updated gets called too many times from other places as well; if we use that signal we get the notification three times - + self.interface.network.trigger_callback('updated') + self.interface.network.trigger_callback("new_transaction") # Updated gets called too many times from other places as well; if we use that signal we get the notification three times self.was_updated = False