Make interface status tri-state.

This allows us to distinguish between connecting and connected
state in interface.py (used to be done in network.py but that
had other issues).

This means we don't switch to a connecting server, and get_interfaces()
does not report connecting ones.
This commit is contained in:
Neil Booth 2015-05-23 22:59:29 +09:00
parent ed256e064a
commit 76355e66c8
2 changed files with 25 additions and 16 deletions

View File

@ -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):
@ -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
@ -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
@ -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)
@ -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))

View File

@ -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:
@ -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'''