tMerge pull request #1270 from kyuupichan/if-tristate - electrum - Electrum Bitcoin wallet
 (HTM) git clone https://git.parazyd.org/electrum
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
       ---
 (DIR) commit 832369d7c444270bbd562798a438e6c460c1c85c
 (DIR) parent 0938299e9bf858817d3c391ebcdca3d48d5dd3d4
 (HTM) Author: ThomasV <electrumdev@gmail.com>
       Date:   Mon,  1 Jun 2015 13:09:40 +0200
       
       Merge pull request #1270 from kyuupichan/if-tristate
       
       Make interface status tri-state.
       Diffstat:
         M lib/interface.py                    |      32 +++++++++++++++++++------------
         M lib/network.py                      |       9 +++++----
       
       2 files changed, 25 insertions(+), 16 deletions(-)
       ---
 (DIR) diff --git a/lib/interface.py b/lib/interface.py
       t@@ -48,6 +48,9 @@ def Interface(server, response_queue, config = None):
            else:
                raise Exception('Unknown protocol: %s'%protocol)
        
       +# Connection status
       +CS_OPENING, CS_CONNECTED, CS_FAILED = range(3)
       +
        class TcpInterface(threading.Thread):
        
            def __init__(self, server, response_queue, config = None):
       t@@ -57,9 +60,8 @@ class TcpInterface(threading.Thread):
                # Set by stop(); no more data is exchanged and the thread exits after gracefully
                # closing the socket
                self.disconnect = False
       -        # Initially True to avoid a race; set to False on failure to create a socket or when
       -        # it is closed
       -        self.connected = True
       +        self._status = CS_OPENING
       +        self.needs_shutdown = True
                self.debug = False # dump network messages. can be changed at runtime using the console
                self.message_id = 0
                self.response_queue = response_queue
       t@@ -275,11 +277,13 @@ class TcpInterface(threading.Thread):
                    self.message_id += 1
        
            def is_connected(self):
       -        return self.connected and not self.disconnect
       +        '''True if status is connected'''
       +        return self._status == CS_CONNECTED and not self.disconnect
        
            def stop(self):
       -        self.disconnect = True
       -        self.print_error("disconnecting")
       +        if not self.disconnect:
       +            self.disconnect = True
       +            self.print_error("disconnecting")
        
            def maybe_ping(self):
                # ping the server with server.version
       t@@ -299,7 +303,8 @@ class TcpInterface(threading.Thread):
                        return
                    # If remote side closed the socket, SocketPipe closes our socket and returns None
                    if response is None:
       -                self.connected = False  # Don't re-close the socket
       +                self.needs_shutdown = False  # Don't re-close the socket
       +                self.disconnect = True
                        self.print_error("connection closed remotely")
                    else:
                        self.process_response(response)
       t@@ -310,22 +315,25 @@ class TcpInterface(threading.Thread):
                    self.pipe = util.SocketPipe(s)
                    s.settimeout(0.1)
                    self.print_error("connected")
       +            self._status = CS_CONNECTED
                    # Indicate to parent that we've connected
       -            self.change_status()
       +            self.notify_status()
                    while self.is_connected():
                        self.maybe_ping()
                        self.send_requests()
                        self.get_and_process_response()
       -            if self.connected:  # Don't shutdown() a closed socket
       +            if self.needs_shutdown:
                        s.shutdown(socket.SHUT_RDWR)
                        s.close()
        
                # Also for the s is None case 
       -        self.connected = False
       +        self._status = CS_FAILED
                # Indicate to parent that the connection is now down
       -        self.change_status()
       +        self.notify_status()
        
       -    def change_status(self):
       +    def notify_status(self):
       +        '''Notify owner that we have just connected or just failed the connection.
       +        Owner determines which through e.g. testing is_connected()'''
                self.response_queue.put((self, None))
        
        
 (DIR) diff --git a/lib/network.py b/lib/network.py
       t@@ -259,7 +259,8 @@ class Network(util.DaemonThread):
                return self.config.get('auto_connect', False)
        
            def get_interfaces(self):
       -        return self.interfaces.keys()
       +        '''The interfaces that are in connected state'''
       +        return [s for s, i in self.interfaces.items() if i.is_connected()]
        
            def get_servers(self):
                if self.irc_servers:
       t@@ -339,9 +340,9 @@ class Network(util.DaemonThread):
                    self.switch_lagging_interface()
        
            def switch_to_random_interface(self):
       -        if self.interfaces:
       -            server = random.choice(self.interfaces.keys())
       -            self.switch_to_interface(server)
       +        servers = self.get_interfaces()    # Those in connected state
       +        if servers:
       +            self.switch_to_interface(random.choice(servers))
        
            def switch_lagging_interface(self, suggestion = None):
                '''If auto_connect and lagging, switch interface'''